首页 > 解决方案 > Ajax 调用返回旧的 ASP.NET MVC 部分视图而不是更新的视图

问题描述

我有一个由按钮触发的 Ajax 调用,它调用控制器来更新部分视图。控制器返回一个更新的局部视图,但是在 Ajax 调用的成功函数中接收到的局部视图是原始视图,而不是更新后的视图。

我创建了一个示例 ASP.NET MVC 程序来重现该问题。该程序在表格中显示客户列表,如下所示。

用户界面快照

文本框在局部视图 _Status 中呈现。单击 Toggle Status 按钮时,通过 Ajax 调用控制器以在真假之间切换客户的状态,并刷新相应文本框的局部视图。问题是状态永远不会改变。这是为什么?

更新

我刚刚在控制器的状态动作中添加了以下代码行,现在,Ajax 成功函数正确接收更新的局部视图!

this.ModelState.Clear();

有人可以解释为什么吗?

这是显示初始视图的 Index.cshtml 视图。

@model IEnumerable<ComboModel.Models.CustomerSummary>

<script type="text/javascript">
    function updatePartialView(id) {
        debugger;
        $.ajax({
            url: "/CustomerSummary/Status",
            data: $('#' + id + ' :input').serialize(),
            dataType: "HTML",
            type: "POST",
            success: function (partialView) {
                // Here the received partial view is not the one created in
                // the controller, but the original view. Why is that?
                debugger;
                $('#' + id).replaceWith(partialView);
            },
            error: function (err) {
                debugger;
            },
            failure: function (err) {
                debugger;
            }
        });
    }
</script>

<h2>Customer Summary</h2>
<table>
    <tr>
        <th>Name</th>
        <th>Active?</th>
        <th>Toggle</th>
    </tr>

    @foreach (var summary in Model)
    {
        <tr>
            <td>@summary.FirstName @summary.LastName</td>
            @Html.Partial("_Status", summary.Input)
            <td><button type="button" name="@("S" + summary.Input.Number)" onclick="updatePartialView(this.name)">Toggle Status</button></td>
        </tr>
    }
</table>

_Status.cshtml 部分视图。

@model ComboModel.Models.CustomerSummary.CustomerSummaryInput

<td id="@("S" + Model.Number)">
    @Html.TextBoxFor(model => model.Active)
    <input type="hidden" value="@Model.Number" name="Number" />
</td>

CustomerSummaryController.cs。

using System.Collections.Generic;
using System.Web.Mvc;
using ComboModel.Models;

namespace ComboModel.Controllers
{
    public class CustomerSummaryController : Controller
    {
        private readonly CustomerSummaries _customerSummaries = new CustomerSummaries();

        public ViewResult Index()
        {
            IEnumerable<CustomerSummary> summaries = _customerSummaries.GetAll();
            return View(summaries);
        }

        public PartialViewResult Status(CustomerSummary.CustomerSummaryInput input)
        {
            this.ModelState.Clear(); // If I add this, things work. Why?
            input.Active = input.Active == "true" ? "false" : "true";
            return PartialView("_Status", input);
        }
    }

    public class CustomerSummaries
    {
        public IEnumerable<CustomerSummary> GetAll()
        {
            return new[]
            {
                new CustomerSummary
                {
                    Input = new CustomerSummary.CustomerSummaryInput {Active = "true", Number = 0},
                    FirstName = "John",
                    LastName = "Smith"
                },
                new CustomerSummary
                {
                    Input = new CustomerSummary.CustomerSummaryInput {Active = "false", Number = 1},
                    FirstName = "Susan",
                    LastName = "Power"
                },
                new CustomerSummary
                {
                    Input = new CustomerSummary.CustomerSummaryInput {Active = "true", Number = 2},
                    FirstName = "Jim",
                    LastName = "Doe"
                },
            };
        }
    }
}

最后是 CustomerSummary.cs 模型。

namespace ComboModel.Models
{
    public class CustomerSummary
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }

        public CustomerSummaryInput Input { get; set; }

        public class CustomerSummaryInput
        {
            public int Number { get; set; }
            public string Active { get; set; }
        }
    }
}

谢谢!

标签: ajaxasp.net-mvcasp.net-ajaxpartial-viewsasp.net-mvc-partialview

解决方案


这是Asp.net MVC ModelState.Clear的副本。

在当前场景下,因为没有验证status字段,所以清除ModelState就可以了。但是,MVC 正确的方法是将状态值(true 或 false)传递给控制器​​中的 GET 操作,切换值,返回结果字符串,然后更新页面上的文本框。


推荐阅读