问题描述
我有一个由按钮触发的 Ajax 调用,它调用控制器来更新局部视图。控制器返回更新后的局部视图,但是Ajax调用的成功函数中接收到的局部视图是原始视图,而不是更新后的视图。
我创建了一个示例 ASP.NET MVC 程序来重现该问题。该程序在表格中显示客户列表,如下所示。
文本框在局部视图_Status 中呈现。当点击切换状态按钮时,通过Ajax调用控制器来切换客户的状态真假,并刷新对应文本框的局部视图。问题是状态永远不会改变。这是为什么?
更新
我刚刚在控制器的Status action中添加了下面这行代码,现在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; }
}
}
}
谢谢!
解决方法
这是 Asp.net MVC ModelState.Clear 的副本。
在当前场景下,因为没有验证status字段,所以清除ModelState就可以了。但是,MVC 的正确方法是将状态值(true 或 false)传递给控制器中的 GET 操作,切换该值,返回结果字符串,并更新页面上的文本框。