使用 EditorFor 时模型值被 Request.Form 覆盖
Model values overridden by Request.Form when using EditorFor
我正在构建一个向导 - 一系列表单步骤。
向导的每一步都提交给同一个action方法(需要高度可扩展),所有步骤的viewmodels都继承自同一个base model。它们通过自定义模型绑定器绑定到它们的具体类型。提交操作保存表单字段和 returns 下一步(或相同的错误情况)。
效果很好。但是,用户有时需要提供工作信息。紧随主要工作之后的步骤是次要工作信息 - 相同的形式,相同的属性。第二部分的视图模型继承自主视图模型,没有实现任何单独的属性(class 定义为空)。
提交主要表单后,返回次要视图模型并重置值。但是,出于某种原因,表单显示为第一个视图模型值。
真正奇怪的是,模型值被所有 EditorFor 调用的 Request.Form 值覆盖,但不是特定调用:
// This displays correctly, showing the current model values
<div>Model says: @Model.AuthorizationNumber</div>
<div><input type="text" value="@Model.AuthorizationNumber"/></div>
// This displays the Request.Form value from the previous step.
@Html.EditorFor(x => x.AuthorizationNumber)
在上面,前两行(构造函数值)正确显示授权号,但第三行不正确(显示 Request.Form 值)。
可能是什么问题?
编辑 1
根据请求,处理提交的控制器方法。
public ActionResult Index(StepPathState model = null)
{
var isPreviousSubmit = Request.Form.AllKeys.Contains("submit-previous");
if (model == null || model.Step == null) return View(Steps.GetFirstPathResult());
// submit the step data
var result = Steps.SubmitStepData(model, isPreviousSubmit);
if (result.Status is StepSuccessAndFinish)
{
return Finish(result);
}
var failureStatus = result.Status as StepActionStatusFailure;
if (failureStatus != null)
{
foreach (var error in failureStatus.Errors)
{
ModelState.AddModelError(error.Property, error.ErrorMessage);
}
}
return View(result);
}
不过我可能已经找到答案了:http://blogs.msdn.com/b/simonince/archive/2010/05/05/asp-net-mvc-s-html-helpers-render-the-wrong-value.aspx
解决方案:善与恶
正如上面链接的文章所述,从 POST 返回时,MVC 似乎更喜欢模型状态值。这是因为在 POST 中重新显示表单应该始终表示验证失败。所以正确的解决方案是保存,重定向到 GET 请求并显示新表单。这将解决问题,这就是我有时间重构时要做的事情。
临时解决方案是清除模型状态。这将导致它回退到模型。这是我的临时修复:
if (failureStatus == null && ModelState.IsValid)
{
ModelState.Clear();
}
return View(result);
这里的危险是我已经清除了模型状态。在漫长的 运行 中,这可能意味着什么?新的错误冒险即将到来。但是我在上班。
我正在构建一个向导 - 一系列表单步骤。
向导的每一步都提交给同一个action方法(需要高度可扩展),所有步骤的viewmodels都继承自同一个base model。它们通过自定义模型绑定器绑定到它们的具体类型。提交操作保存表单字段和 returns 下一步(或相同的错误情况)。
效果很好。但是,用户有时需要提供工作信息。紧随主要工作之后的步骤是次要工作信息 - 相同的形式,相同的属性。第二部分的视图模型继承自主视图模型,没有实现任何单独的属性(class 定义为空)。
提交主要表单后,返回次要视图模型并重置值。但是,出于某种原因,表单显示为第一个视图模型值。
真正奇怪的是,模型值被所有 EditorFor 调用的 Request.Form 值覆盖,但不是特定调用:
// This displays correctly, showing the current model values
<div>Model says: @Model.AuthorizationNumber</div>
<div><input type="text" value="@Model.AuthorizationNumber"/></div>
// This displays the Request.Form value from the previous step.
@Html.EditorFor(x => x.AuthorizationNumber)
在上面,前两行(构造函数值)正确显示授权号,但第三行不正确(显示 Request.Form 值)。
可能是什么问题?
编辑 1
根据请求,处理提交的控制器方法。
public ActionResult Index(StepPathState model = null)
{
var isPreviousSubmit = Request.Form.AllKeys.Contains("submit-previous");
if (model == null || model.Step == null) return View(Steps.GetFirstPathResult());
// submit the step data
var result = Steps.SubmitStepData(model, isPreviousSubmit);
if (result.Status is StepSuccessAndFinish)
{
return Finish(result);
}
var failureStatus = result.Status as StepActionStatusFailure;
if (failureStatus != null)
{
foreach (var error in failureStatus.Errors)
{
ModelState.AddModelError(error.Property, error.ErrorMessage);
}
}
return View(result);
}
不过我可能已经找到答案了:http://blogs.msdn.com/b/simonince/archive/2010/05/05/asp-net-mvc-s-html-helpers-render-the-wrong-value.aspx
解决方案:善与恶
正如上面链接的文章所述,从 POST 返回时,MVC 似乎更喜欢模型状态值。这是因为在 POST 中重新显示表单应该始终表示验证失败。所以正确的解决方案是保存,重定向到 GET 请求并显示新表单。这将解决问题,这就是我有时间重构时要做的事情。
临时解决方案是清除模型状态。这将导致它回退到模型。这是我的临时修复:
if (failureStatus == null && ModelState.IsValid)
{
ModelState.Clear();
}
return View(result);
这里的危险是我已经清除了模型状态。在漫长的 运行 中,这可能意味着什么?新的错误冒险即将到来。但是我在上班。