在 MVC 中 Ajax post 之后无法更新 Partialview
Cannot update Partialview after Ajax post in MVC
在我的 MVC 应用程序中,有一个视图(详细信息),所有评论都通过部分视图(_Comment)列出,如下所示:
还有一个用于添加新评论的编辑器,我使用 Ajax 调用它,然后我想通过使用一些参数重新调用 partialview (评论正文、日期、用户)。
注意:为简洁起见,省略了不必要的代码。
部分视图:
@model Domain.Entities.Comment
@if (Model != null) {
@Html.Raw(string.Format("<div id='comments' class='issue-data-block'> {0} </div>",
Model.Comment ))
}
@if (TempData["newComment "] != null)
{
@Html.Raw(string.Format("<div id='comments' class='issue-data-block'> {0} </div>", TempData["newComment"] ))
}
查看:
@model IssueViewModel
@foreach (var com in Model.Comments)
{
@Html.Partial("_Comment", com)
}
<script>
$(function () {
$('form').submit(function (event) {
event.preventDefault();
kendo.ui.progress($("#kendo-loading"), true);
$.ajax({
type: "POST",
url: "/Issue/CreateComment",
cache: false,
//Later I will retrieve these values dynamically
data: {
id: "1",
comment : $('#comment.text').val()
},
//I have no idea about the parameter values below:
dataType: "json",
//contentType: "application/json; charset=utf-8",
//processData: false,
//contentType: false,
traditional: true,
complete: function () {
kendo.ui.progress($("#kendo-loading"), false);
},
success: function (response) {
if (response.success) {
//Here I want to recall the partialview by sending
//some parameters returned from the Controller
// ???
@Html.Partial("_Comment", new ViewDataDictionary { { "Commment ", response.newComment } })
}
},
error: function (data) {
// $("#error_message").html(data);
}
}); //End of ajax call
});
控制器:
[HttpPost]
public ActionResult CreateComment([Bind(Exclude = null)] int id, string comment)
{
Domain.Entities.Comment comment = new Domain.Entities.Comment ();
comment .ActionBody = comment;
comment .ActionTypeID = id;
repository.SaveAction(action);
return Json(new { success = true, newComment = commment });
}
尽管我尝试了很多不同的方法,例如传递模型、字典、字符串、json 等。在此过程中我遇到了下面解释的一些问题,但未能正确完成:
1) 我认为在创建新评论时没有必要将整个模型传递给控制器。与其如此,我认为最好将其传递到字典中。您有什么更好的方法可以建议吗?
2) 我想将新添加的评论追加到最后一条评论的底部。于是,我试图回忆一下Ajax成功的部分观点,但没有成功。通过向其发送新添加的评论来再次召回部分视图是正确的方法吗?如果是这样,我该怎么做?
下面是@Stephen Muecke 出色解决方案的工作和更新代码。我希望这对那些寻找这种解决方案或方法的人也有用。再次非常感谢@Stephen Muecke 的帮助和聪明的解决方案:) 请注意,为简洁起见,所有不必要的代码都已删除。
查看:
@using (Html.BeginForm("CreateComment", "Issue", FormMethod.Post,
new { id = "frmDetails" }))
{
<div id="comments">
@foreach (var action in Model.Actions)
{
//List each comment in Actions with the given format :
@Html.Raw(string.Format("<div class='issue-data-block'><a href=''><strong>{0}</strong></a>| {1} <br /><p> {2} </p></div>",
action.AuthorID, action.Created.ToString("dd/MM/yyyy - HH:mm"), action.ActionBody))
}
</div>
@*New comments first rendered on here before appending to the "comments" div above*@
<div id="template" class="hidden">
<div class="issue-data-block"></div>
</div>
<div class="pull-left">
@(Html.Kendo().Button().Name("btnComment"))
</div>
<div id="addComment" style="display: none; ">
@(Html.Kendo().EditorFor(m => m.Action.ActionBody)
.Name("CommentBody")
)
@Html.ValidationMessageFor(m => m.Action.ActionBody)
<br />
<div class="pull-left">
@(Html.Kendo().Button().Name("btnCancelComment"))
@(Html.Kendo().Button().Name("btnAddComment"))
</div>
</div>
}
<script>
var decodeEntities = (function () {
// this prevents any overhead from creating the object each time
var element = document.createElement('div');
function decodeHTMLEntities(str) {
if (str && typeof str === 'string') {
// strip script/html tags
str = str.replace(/<script[^>]*>([\S\s]*?)<\/script>/gmi, '');
str = str.replace(/<\/?\w(?:[^"'>]|"[^"]*"|'[^']*')*>/gmi, '');
element.innerHTML = str;
str = element.textContent;
element.textContent = '';
}
return str;
}
return decodeHTMLEntities;
})();
//returns raw Html from given string
function RawHtml(str) {
return $('<div/>').html(str).text();
}
$('#btnAddComment').click(function () {
var url = '@Url.Action("AddComment")';
var issueId = '@Model.ID';
var commentBody = $("#CommentBody").val();
var token = $('[name=__RequestVerificationToken]').val();
var existingComments = $('#comments');
var comment = decodeEntities(commentBody);
$.post(url, { comment: comment, IssueID: issueId, __RequestVerificationToken: token }, function (data) {
if (!data.success) {
return;
}
else if (data.success) {
var newComment = $('#template').children('div').clone();
newComment.text(comment);
var comm = "<div class='issue-data-block'><a href=''><strong>" + data.userId + "</strong></a>| " + data.created + " <br /><p> " + RawHtml(newComment) + " </p></div>";
existingComments.append(comm);
//Clear Kendo Editor content
var editor = $("#CommentBody").data("kendoEditor");
editor.value('');
}
}).error(function (data) {
// oops something went wrong
});
});
</script>
控制器:
[HttpPost, ValidateInput(false)]
[ValidateAntiForgeryToken]
public JsonResult AddComment(string comment, int IssueID)
{
if (!string.IsNullOrEmpty(comment))
{
Action action = new Action();
action.ActionBody = comment;
action.IssueID = IssueID;
repository.SaveAction(action);
return Json(new { success = true, userId = GetUser.Id, created = action.Created.ToString("dd/MM/yyyy - HH:mm") });
}
return Json(new { success = false, message = "Error..." }, JsonRequestBehavior.AllowGet);
}
在我的 MVC 应用程序中,有一个视图(详细信息),所有评论都通过部分视图(_Comment)列出,如下所示:
还有一个用于添加新评论的编辑器,我使用 Ajax 调用它,然后我想通过使用一些参数重新调用 partialview (评论正文、日期、用户)。
注意:为简洁起见,省略了不必要的代码。
部分视图:
@model Domain.Entities.Comment
@if (Model != null) {
@Html.Raw(string.Format("<div id='comments' class='issue-data-block'> {0} </div>",
Model.Comment ))
}
@if (TempData["newComment "] != null)
{
@Html.Raw(string.Format("<div id='comments' class='issue-data-block'> {0} </div>", TempData["newComment"] ))
}
查看:
@model IssueViewModel
@foreach (var com in Model.Comments)
{
@Html.Partial("_Comment", com)
}
<script>
$(function () {
$('form').submit(function (event) {
event.preventDefault();
kendo.ui.progress($("#kendo-loading"), true);
$.ajax({
type: "POST",
url: "/Issue/CreateComment",
cache: false,
//Later I will retrieve these values dynamically
data: {
id: "1",
comment : $('#comment.text').val()
},
//I have no idea about the parameter values below:
dataType: "json",
//contentType: "application/json; charset=utf-8",
//processData: false,
//contentType: false,
traditional: true,
complete: function () {
kendo.ui.progress($("#kendo-loading"), false);
},
success: function (response) {
if (response.success) {
//Here I want to recall the partialview by sending
//some parameters returned from the Controller
// ???
@Html.Partial("_Comment", new ViewDataDictionary { { "Commment ", response.newComment } })
}
},
error: function (data) {
// $("#error_message").html(data);
}
}); //End of ajax call
});
控制器:
[HttpPost]
public ActionResult CreateComment([Bind(Exclude = null)] int id, string comment)
{
Domain.Entities.Comment comment = new Domain.Entities.Comment ();
comment .ActionBody = comment;
comment .ActionTypeID = id;
repository.SaveAction(action);
return Json(new { success = true, newComment = commment });
}
尽管我尝试了很多不同的方法,例如传递模型、字典、字符串、json 等。在此过程中我遇到了下面解释的一些问题,但未能正确完成:
1) 我认为在创建新评论时没有必要将整个模型传递给控制器。与其如此,我认为最好将其传递到字典中。您有什么更好的方法可以建议吗?
2) 我想将新添加的评论追加到最后一条评论的底部。于是,我试图回忆一下Ajax成功的部分观点,但没有成功。通过向其发送新添加的评论来再次召回部分视图是正确的方法吗?如果是这样,我该怎么做?
下面是@Stephen Muecke 出色解决方案的工作和更新代码。我希望这对那些寻找这种解决方案或方法的人也有用。再次非常感谢@Stephen Muecke 的帮助和聪明的解决方案:) 请注意,为简洁起见,所有不必要的代码都已删除。
查看:
@using (Html.BeginForm("CreateComment", "Issue", FormMethod.Post,
new { id = "frmDetails" }))
{
<div id="comments">
@foreach (var action in Model.Actions)
{
//List each comment in Actions with the given format :
@Html.Raw(string.Format("<div class='issue-data-block'><a href=''><strong>{0}</strong></a>| {1} <br /><p> {2} </p></div>",
action.AuthorID, action.Created.ToString("dd/MM/yyyy - HH:mm"), action.ActionBody))
}
</div>
@*New comments first rendered on here before appending to the "comments" div above*@
<div id="template" class="hidden">
<div class="issue-data-block"></div>
</div>
<div class="pull-left">
@(Html.Kendo().Button().Name("btnComment"))
</div>
<div id="addComment" style="display: none; ">
@(Html.Kendo().EditorFor(m => m.Action.ActionBody)
.Name("CommentBody")
)
@Html.ValidationMessageFor(m => m.Action.ActionBody)
<br />
<div class="pull-left">
@(Html.Kendo().Button().Name("btnCancelComment"))
@(Html.Kendo().Button().Name("btnAddComment"))
</div>
</div>
}
<script>
var decodeEntities = (function () {
// this prevents any overhead from creating the object each time
var element = document.createElement('div');
function decodeHTMLEntities(str) {
if (str && typeof str === 'string') {
// strip script/html tags
str = str.replace(/<script[^>]*>([\S\s]*?)<\/script>/gmi, '');
str = str.replace(/<\/?\w(?:[^"'>]|"[^"]*"|'[^']*')*>/gmi, '');
element.innerHTML = str;
str = element.textContent;
element.textContent = '';
}
return str;
}
return decodeHTMLEntities;
})();
//returns raw Html from given string
function RawHtml(str) {
return $('<div/>').html(str).text();
}
$('#btnAddComment').click(function () {
var url = '@Url.Action("AddComment")';
var issueId = '@Model.ID';
var commentBody = $("#CommentBody").val();
var token = $('[name=__RequestVerificationToken]').val();
var existingComments = $('#comments');
var comment = decodeEntities(commentBody);
$.post(url, { comment: comment, IssueID: issueId, __RequestVerificationToken: token }, function (data) {
if (!data.success) {
return;
}
else if (data.success) {
var newComment = $('#template').children('div').clone();
newComment.text(comment);
var comm = "<div class='issue-data-block'><a href=''><strong>" + data.userId + "</strong></a>| " + data.created + " <br /><p> " + RawHtml(newComment) + " </p></div>";
existingComments.append(comm);
//Clear Kendo Editor content
var editor = $("#CommentBody").data("kendoEditor");
editor.value('');
}
}).error(function (data) {
// oops something went wrong
});
});
</script>
控制器:
[HttpPost, ValidateInput(false)]
[ValidateAntiForgeryToken]
public JsonResult AddComment(string comment, int IssueID)
{
if (!string.IsNullOrEmpty(comment))
{
Action action = new Action();
action.ActionBody = comment;
action.IssueID = IssueID;
repository.SaveAction(action);
return Json(new { success = true, userId = GetUser.Id, created = action.Created.ToString("dd/MM/yyyy - HH:mm") });
}
return Json(new { success = false, message = "Error..." }, JsonRequestBehavior.AllowGet);
}