MVC 3 – Html.EditorFor似乎caching$ .ajax调用后的旧值

这是从以下问题的后续:

MVC 3 + $ .ajax – 响应似乎是从部分视图caching输出

这里有详细的问题描述。 不过,现在我已经设法缩小了这个问题的范围,这似乎与Html.EditorFor的助手,因此,新的问题。

问题:

我使用$ .ajax将数据发布到服务器,然后返回包含input控件的部分视图的html。 问题是,尽pipe将新创build的对象传递给Partial Views模型,各种@ Html.EditorFor和@ Html.DropDownListFor帮助器将返回OLD DATA !.

我可以通过在Html助手旁边打印值来certificate模型已经正确地将新对象传递给了助手。 即:

@Html.EditorFor(model => model.Transaction.TransactionDate) @Model.Transaction.TransactionDate.ToString() 

如下图所示,@ Html.EditorFor正在返回错误的数据:

缓存响应...

[请注意,Comentario文本框旁边的值是date时间,因为我正在testing用每个post都会更改的值(即DateTime)replace默认值。]

如果我将@ Html.EditorForreplace为旧的@ Html.TextBox():

 @Html.TextBox("Transaction_TransactionDate", Model.Transaction.TransactionDate) 

然后它为新的Transaction对象呈现正确的TransactionDate值,即DateTime.MinValue(01/01/0001 …)。

因此…

问题出在@ Html.EditorFor帮手。 TextBoxFor和DropDownListFor也会出现问题。

问题是这些助手似乎caching了旧的价值。

我究竟做错了什么??!

编辑:

我刚刚尝试在date的自定义编辑器模板中进行debugging,在那里,ViewData.TemplateInfo.FormattedModelValue显示正确的值,即“01/01/0001”。 但是,一旦到了Fiddler,响应就会显示旧的date,例如上图中的“01/09/2011”。

所以我只是觉得这里有一些caching,但是我没有设置,所以没有任何意义。

这里没有涉及caching 。 这只是HTML帮手的工作方式。 他们首先看模型状态时绑定他们的价值,然后在模型中。 因此,如果您打算修改控制器操作中的任何POSTed值,请确保先将它们从模型状态中删除:

 [HttpPost] public virtual ActionResult AjaxCreate(Transaction transaction) { if (ModelState.IsValid) { service.InsertOrUpdate(transaction); service.Save(); } service.ChosenCostCentreId = transaction.IdCostCentre; TransactionViewModel viewModel = new TransactionViewModel(); ModelState.Remove("Transaction"); viewModel.Transaction = new Transaction(); ModelState.Remove("CostCentre"); viewModel.CostCentre = service.ChosenCostCentre; ... return PartialView("_Create", viewModel); } 

即使你没有指定caching,有时也会发生。 对于我的控制器,处理AJAX和JSON请求,我装饰他们如下:

 [OutputCache(Location = OutputCacheLocation.None, NoStore = true)] 

这明确声明不应该发生caching。

UPDATE

根据达林·季米特洛夫(Darin Dimitrov) 在这里给出的答案,尝试在你的控制器动作中添加以下行:

 ModelState.Clear(); 

我从来没有见过这个,但基本上,如果你使用Ajax请求这个数据,你需要设置nochache:我假设你在这里使用jQuery.ajax所以会显示代码:

 $.ajax({ url: "somecontroller/someAction, cache: false, // this is key to make sure JQUERY does not cache your request success: function( data ) { alert( data ); } }); 

只是在黑暗中刺,我想你已经可能已经覆盖了这一点。 您是否尝试过先创build一个新模型,然后用您的数据填充该模型的新实例,然后将其发送到您的视图!

最后不知道你使用什么数据库服务器,但你检查,看看数据库结果没有caching,你不只是从数据库caching请求SQL结果…我不使用MsSQL,但我听说它有输出caching,直到有东西在DB服务器本身上更改? 无论如何只是几个想法

这对我来说是意外的行为,虽然我理解为什么有必要赋予ModelState优先级,但我需要一种方法来删除该条目,以便使用来自Model的值。

这里有几个方法,我想出来协助这个。 RemoveStateFor方法将获取所需属性的ModelStateDictionary ,Model和expression式,并将其删除。

可以在视图中使用HiddenForModel ,只使用Model中的值创build一个隐藏的input字段,方法是先删除其ModelState条目。 (这可以很容易地扩展为其他助手扩展方法)。

 /// <summary> /// Returns a hidden input field for the specified property. The corresponding value will first be removed from /// the ModelState to ensure that the current Model value is shown. /// </summary> public static MvcHtmlString HiddenForModel<TModel, TProperty>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression) { RemoveStateFor(helper.ViewData.ModelState, helper.ViewData.Model, expression); return helper.HiddenFor(expression); } /// <summary> /// Removes the ModelState entry corresponding to the specified property on the model. Call this when changing /// Model values on the server after a postback, to prevent ModelState entries from taking precedence. /// </summary> public static void RemoveStateFor<TModel, TProperty>(this ModelStateDictionary modelState, TModel model, Expression<Func<TModel, TProperty>> expression) { var key = ExpressionHelper.GetExpressionText(expression); modelState.Remove(key); } 

从这样的控制器调用:

 ModelState.RemoveStateFor(model, m => m.MySubProperty.MySubValue); 

或从这样的视图:

 @Html.HiddenForModel(m => m.MySubProperty.MySubValue) 

它使用System.Web.Mvc.ExpressionHelper来获取ModelState属性的名称。 由于密钥名称不明显,因此当您使用“嵌套”模式时,此function特别有用。

确保你没有这样做:

 @Html.EditorFor(model => model.Transaction.TransactionDate.Date) 

我这样做,模型从来没有得到回报。 一旦我删除了.Date完美.Date