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
。