【问题标题】:Issue with updating model on AJAX "POST"在 AJAX“POST”上更新模型的问题
【发布时间】:2014-09-04 12:43:12
【问题描述】:

我正在尝试更新我的模型而不刷新页面。我正在使用我页面上许多地方的所见即所得内联编辑器。编辑器可以放置在页面的任何位置,它可能看起来像这样:

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

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

每个编辑器div 都有一个保存按钮,可以转到这个 jquery,下面的 ajax。 它的作用是:当我点击保存按钮时,例如&lt;div id="1" class="click2edit"&gt;@Model.Header&lt;/div&gt; 它发布 div 的 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...
}

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

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

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

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

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

【问题讨论】:

  • Ajax 由两部分组成:1)在没有回发的情况下更新幕后数据(你有这部分),2)更新视图以反映这些变化。真正将新的“模型”呈现为整个视图的唯一方法是将需要更改的视图部分作为完整的标记返回给您的操作(通常您不希望将 void 方法作为操作MVC)。您需要在成功函数中以任何方式更改视图(其中数据由您的操作方法提供)。
  • @xDaevax 感谢您的回答。你的意思是我需要做的是将我的 void-method 作为 ActionResult 。然后,将我的整个模型返回到我的成功函数。当它恢复成功时,我需要在那里做一些事情来更新我的内容吗?我真的不明白。
  • @xDaevax 我现在将我的方法更改为 ActoinResult 并将我的模型返回为 Json。 json 正在返回视图成功数据。如果这是一个正确的方法,那么我应该做什么来用这些值更新我的模型?
  • 这取决于你需要什么。如果您只是更新模型的标头和内容属性(假设这些在success 的数据参数中返回),那么您只需要定位这些 div 并在您的成功方法中替换它们的内容:$("#1").text(data.Header);例如。
  • @xDaevax 请看我的编辑! =)

标签: jquery ajax asp.net-mvc razor


【解决方案1】:

以下是我们聊天的摘要:

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

在此之后,您不能再使用 Razor 服务器端语法 @if@model 来访问模型数据(在呈现页面时存在的模型不再存在)。相反,您应该使用 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)代码在ajax方法的success回调和getFormData()方法中负责更新视图用于将表单值转换为 MVC 模型绑定器可以读取的 JavaScript 对象,并将其转换为 .NET 服务器端模型。如果您不想手动执行此操作,可以使用 JQuery 的 serialize 方法序列化整个表单,前提是表单值与您的服务器端模型匹配。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-08-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-27
    • 2021-07-23
    • 1970-01-01
    相关资源
    最近更新 更多