在 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);
}