Ajax.BeginForm() を使用してデータ (コメント フォーム) をコントローラー メソッドに投稿する状況があります。次に、このコントローラー メソッドは、Entity Framework を使用して (ModelState が有効である限り) データベースにいくつかの情報を書き込みます。
フォームの一部として、OnSucess オーバーロードを使用して、フォームが投稿された後に JavaScript 関数を実行します。この関数は、基本的に別のコントローラー メソッドを呼び出します (このメソッドは部分的なビューを返します。この場合はコメントのリストです)。
私の問題は、データベース内に存在することはわかっていますが、新しく追加されたコメントがコントローラーアクションから返されたビューに含まれていないことです。
これにより、2つの可能なオプションが得られます。
- コントローラ メソッドが実際に戻る前に、フォーム htmlhelper の OnSucess() 関数が実行されています。
- Entity Framework がデータをキャッシュしています。
2 の場合、明示的に指示されない限り、エンティティ フレームワークがデータをキャッシュしていることを認識していません。だから1だと思った。
さらに調査を進めるために、OnSucess メソッドとコントローラー アクションを変更しました。
私のフォーム定義は次のとおりです。
@using (Ajax.BeginForm("CreateComment", "Home", new AjaxOptions { HttpMethod = "POST", OnSuccess = "something" })){
...
}
そして、私のコントローラーアクションは次のように定義されています(明確にするために詳細は省略されています):
public ActionResult CreateComment(CreateCommentViewModel comment)
{
if (ModelState.IsValid)
{
var context = new myDataContext();
var newComment = new BlogComment
{
BlogID = comment.BlogID,
CommentContent = comment.CommentContent,
CommentDateCreated = DateTime.Now,
CommentDeleted = false,
CommentLive = true,
CommenterEmail = comment.CommenterEmail,
CommenterName = comment.CommenterName
};
var errorList = new List<string>();
context.BlogComments.Add(newComment);
try
{
context.SaveChanges();
}
catch (DbEntityValidationException dbEx)
{
errorList.AddRange(from validationErrors in dbEx.EntityValidationErrors from validationError in validationErrors.ValidationErrors select string.Format("Property: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage));
}
finally {
return Json(new { result = -2, message = "Error saving to database" }); // Not currently handled client side
}
return Json(new { result = 0, message = "Sucess" });
}else
{
var errorList = (from modelState in ViewData.ModelState.Values from error in modelState.Errors select error.ErrorMessage).ToList();
string message = errorList.Aggregate(string.Empty, (current, errorMessage) => current + (errorMessage + ","));
return Json(new { result = -1, message = message });
}
}
最後に、クライアント側のメソッドは次のように定義されます。
function something(data) {
switch (data.result) {
case 0:
// Sucess
// Get the Alert
var message = "<strong>Thank You</strong> Your comment has been posted.";
var myAlert = jQuery("#donemessage");
myAlert.html(message);
reloadBlogComments();
break;
case -1:
var errorMessages = data.message.split(',');
var html = "<strong>The following errors were detected:</strong><br/>";
var length = errorMessages.length, element = null;
for (var i = 0; i < length; i++) {
element = errorMessages[i];
// Do something with element i.
html += element + "<br/>";
}
var myErrorAlert = jQuery("#failmessage");
myErrorAlert.html(html);
myErrorAlert.show(500).css("visibility", "visible");
break;
default:
alert(data.message);
break;
}
}
戻り値が 0 の場合、関数 reloadBlogComments() が呼び出されます。
ただし、上記の変更は、上記の最初の仮定 (1) が実際には間違っていることを証明しています。コントローラーが値を返す前に、success 関数を実行することはできません。そのため、新しく追加されたコメントが残りのコメントと共に返されない理由について、私は完全に途方に暮れています。
私の reloadBlogComments() 関数は次のように定義されています。
function reloadBlogComments() {
jQuery.ajax({
// edit to add steve's suggestion.
//url: "/ControllerName/ActionName",
url: '@Url.Action("RenderBlogComments", "Home")',
data: { 'BlogID': '@Model.BlogID' },
success: function (newdata) {
jQuery("#upComments").empty().html(newdata);
},
statusCode: {
404: function (content) { alert('cannot find resource'); },
505: function (content) { alert('internal server error'); }
},
error: function (req, status, errorObj) {
// handle status === "timeout"
// handle other errors
}
});
var myAlert = jQuery("#donemessage");
var myErrorAlert = jQuery("#failmessage");
myErrorAlert.hide(500).css("visibility", "hidden");
myAlert.show(500).css("visibility", "visible");
// Clear the form
jQuery('#CommenterName').val('');
jQuery('#CommenterEmail').val('');
jQuery('#CommentContent').val('');
window.location.hash = '#comments';
}
を使用して reloadBlogComments() の呼び出しを遅らせても、一貫した setTimeout(function () { reloadBlogComments(); }, 3000);
値は得られません。
ここでどこが間違っていますか?