在AJAX“POST”上更新模型的问题

时间:2014-09-04 12:43:12

标签: jquery ajax asp.net-mvc razor

我正在尝试更新我的模型而不刷新页面。我正在使用我在页面上很多地方使用的所见即所得内联编辑器。编辑器可以放在页面的任何位置,它可能如下所示:

<div id="1" class="click2edit">@Model.Header</div>

<div id="2" class="click2edit">@Model.Content</div>

每个编辑器div都有一个SaveButton,它转到这个jquery,下面是ajax。 它的作用是:当我点击保存按钮时,例如<div id="1" class="click2edit">@Model.Header</div> 它发布了divs id及其内容(在本例中为@Model.Header)。我的整个@model

$('.click2edit').click(function () {
    var modelDataJson = '@Html.Raw(Json.Encode(Model))';
    $(this).note({ focus: true });
    var activeId = (this.id);
    activeId = activeId.replace(/ /g, '');
    $(this).note({
        oninit: function () {
            $('#saveFileBtn').click(function (event) {
                $('#previewBtn').click(),
                $.ajax({
                    url: '/Home/SaveContent',
                    type: 'POST',
                    data: {
                        model: modelDataJson,
                        activeId: activeId,
                        contentToUpdate: $("div#" + activeId).html()
                    },
                    dataType: 'json',
                    success: function (data) {
                        alert("sucess");
                    },
                    error: function () {
                        alert("error");
                    }
                });
                $('.click2edit').destroy();
            });
        }
    });
});

然后在我的mvc-controller中,它将新内容放在正确的位置并保存到我的数据库中。 这是通过将整个旧模型替换为从视图中发布的新模型来完成的:

[ValidateInput(false)]
public void SaveContent(string model, string activeId, string contentToUpdate)
{
    //my logic to save to db is here...
}

问题是: 我剃刀视图中的模型没有更新。如果我只是保存我的一个编辑器内容,一切正常。但是当我在刷新页面之前尝试保存另一个时,它没有得到更新。 那是因为我的剃刀观点@model仍然持有旧的价值观。 所以基本上唯一更新的值是我将保存的最后一个值。 我可以在没有刷新整个页面的情况下刷新我的观点@model吗?

编辑: 我现在改变了我的成功功能,所以它看起来像这样:

success: function (data) {
    $("#1").text(data.Header);
},

但是模型的价值没有得到更新。我从成功函数发回的数据是我的模型为Json。

<div id="1" class="click2edit">@Model.Header</div>

1 个答案:

答案 0 :(得分:4)

以下是我们聊天的摘要:

MVC模型是一个实例,它包含在服务器上构建的数据,用于控制视图的呈现和向视图提供数据。 HTTP的无状态特性决定了您可以访问此服务器端数据的唯一时间是视图处于呈现过程中。一旦它被渲染,它就完全掌握在浏览器中,并且服务器端对象中存在的任何数据都从内存中释放出来。

在此之后,您无法再使用@if@model的Razor服务器端语法来访问模型数据(呈现页面时存在的模型不再存在)。相反,您应该使用DOM和JavaScript对象来更新页面的外观和内容(同时在服务器端使用Ajax保存数据)。如果不进行整页发布,您唯一的选择是使用客户端代码(JavaScript)来操纵用户看到的内容(因此名称:View),以便他们看到的内容与Ajax POST后发生的更改相匹配。

我在这里创建了一个Gist来演示这些概念:https://gist.github.com/xDaevax/f5e192c03f6a2bfc2cdb

基本上,您需要与控制器类似的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace AjaxMvcTest.Controllers {
    public class HomeController : Controller {
        //
        // GET: /Home/


        public ActionResult Index() {
            HomeModel model = new HomeModel();
            model.Header = "Default Header";
            model.Content = "People assume that time is a strict progression of cause to effect, but actually, from a non-linear, non-subjective viewpoint, it's more like a big ball of wibbly-wobbly... timey-wimey... stuff.";
            return View(model);
        }

        [ValidateInput(false)]
        public JsonResult SaveContent(UpdateDataModel updateRequest) {
            //Do some stuff
            HomeModel newModel = new HomeModel();
            newModel.Content = updateRequest.Content;
            newModel.Header = updateRequest.Header;

            return Json(newModel);
        }

    }
}

以下是与上述控制器一起使用的视图:

@model HomeModel

@{
    ViewBag.Title = "Index";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<h2>Index</h2>

<div id="1" class="click2edit">@Model.Header</div>
<br />
<div id="2" class="click2edit">@Model.Content</div>
<br />
Header:&nbsp;&nbsp; <input type="text" name="HeaderInput" id="HeaderInput" value="@Model.Header" />
<br />
Content: <textarea name="ContentInput" id="ContentInput">@Model.Content</textarea>
<br />
<input type="button" id="saveFileBtn" value="Save" />

<script type="text/javascript">
    $(function () {

        $("#saveFileBtn").click(function (e) {
            $.ajax({
                url: '/Home/SaveContent',
                type: 'POST',
                data: getFormData(),
                dataType: 'json',
                success: function (data) {
                    $("#1").text(data.Header);
                    $("#2").text(data.Content);
                    $("#HeaderInput").val(data.Header);
                    $("#ContentInput").val(data.Content);
                },
                error: function () {
                    alert("error");
                }
            });
        });
    });

    function getFormData() {
    //Convert the form data to a javascript object
        var dataToSubmit = {
            Header: $("#HeaderInput").val(),
            Content: $("#ContentInput").val(),
            TimeStamp: new Date(),
            Id: 1
       };

       return dataToSubmit;
    }
</script>

通过这种方式,您可以看到客户端(JavaScript)代码负责在控制器完成工作后更新success方法的ajax回调中的视图getFormData()方法用于将表单值转换为MVC模型绑定器可以读取并转换为.NET服务器端模型的JavaScript对象。如果您不想手动执行此操作,则可以使用JQuery的serialize方法序列化整个表单,并提供与服务器端模型匹配的表单值。