任何人都可以给我一个关于ModelState在Asp.net MVC中的角色的简洁定义(或者链接到一个) . 特别是我需要知道在什么情况下调用 ModelState.Clear()
是必要或可取的 .
Bit open ended huh ...对不起,我想如果告诉你我在做什么可能会有所帮助:
我在控制器上有一个名为"Page"的编辑操作 . 当我第一次看到表单来更改Page 's details everything loads up fine (binding to a 1241199 object). Then I click a button that generates a value for one of the MyCmsPage object' s字段( MyCmsPage.SeoTitle
)时 . 它生成正常并更新对象然后我返回动作结果与新修改的页面对象,并期望相关的文本框(使用 <%= Html.TextBox("seoTitle", page.SeoTitle)%>
呈现)更新...但是它显示了已加载的旧模型的值 .
我通过使用_1241203来解决它,但我需要知道它为什么/如何工作所以我不只是盲目地做 .
PageController:
[AcceptVerbs("POST")]
public ActionResult Edit(MyCmsPage page, string submitButton)
{
// add the seoTitle to the current page object
page.GenerateSeoTitle();
// why must I do this?
ModelState.Clear();
// return the modified page object
return View(page);
}
Aspx:
<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<MyCmsPage>" %>
....
<div class="c">
<label for="seoTitle">
Seo Title</label>
<%= Html.TextBox("seoTitle", page.SeoTitle)%>
<input type="submit" value="Generate Seo Title" name="submitButton" />
</div>
9 回答
我认为是MVC中的一个错误 . 我今天花了几个小时努力解决这个问题 .
鉴于这种:
视图使用原始模型呈现,忽略更改 . 所以我想,也许它不喜欢我使用相同的模型,所以我尝试这样:
并且视图仍然使用原始模型呈现 . 奇怪的是,当我在视图中放置断点并检查模型时,它具有更改的值 . 但响应流具有旧值 .
最终我发现了你做过的同样的工作:
按预期工作 .
我不认为这是一个“功能”,是吗?
Update:
这不是错误 .
请停止从POST操作返回
View()
. 如果操作成功,请改用PRG并重定向到GET .如果从POST操作返回
View()
,请执行表单验证,并使用内置帮助程序MVC is designed进行操作 . 如果你这样做那么你不应该使用.Clear()
如果您正在使用此操作返回SPA的ajax,请使用web api控制器并忘记
ModelState
,因为您无论如何都不应该使用它 .Old answer:
MVC中的ModelState主要用于描述模型对象的状态,主要与该对象是否有效有关 . This tutorial应该解释很多 .
通常,您不需要清除ModelState,因为它由MVC引擎为您维护 . 在尝试遵守MVC验证最佳实践时,手动清除它可能会导致意外结果 .
您似乎正在尝试为 Headers 设置默认值 . 这应该在模型对象被实例化时(在某个地方或在对象本身 - 无参数的ctor中),在get动作上进行,以便它第一次或完全在客户端(通过ajax或其他)下载到页面这样看起来好像用户输入了它,然后它返回了已发布的表单集合 . 一些如何在接收表单集合时添加此值的方法(在POST操作//编辑中)导致这种奇怪的行为可能导致
.Clear()
似乎适合您 . 相信我 - 你不想使用clear . 尝试其他一个想法 .如果要清除单个字段的值,那么我发现以下技术很有用 .
Note: 将"Key"更改为要重置的字段的名称 .
那么ModelState基本上在验证方面保持了模型的当前状态
ModelErrorCollection: 表示模型尝试绑定值时的错误 . 恩 .
或者像ActionResult中的参数
ValueProviderResult :保留有关尝试绑定到模型的详细信息 . 恩 . AttemptedValue, Culture, RawValue .
必须谨慎使用Clear()方法,因为它可能导致意外结果 . 并且您将失去ModelState的一些不错的属性,如AttemptedValue,MVC在后台使用它来在出错时重新填充表单值 .
我有一个实例,我想更新一个总结形式的模型,并且不想因为性能原因而“重定向到行动” . 隐藏字段的先前值保留在我更新的模型上 - 导致各种问题!
几行代码很快就确定了我想删除的ModelState中的元素(在验证之后),因此在表单中使用了新值: -
我们很多人似乎都被这个咬了,虽然这种情况发生的原因是有道理的,我需要一种方法来确保显示了我的模型上的值,而不是ModelState .
有些人建议
ModelState.Remove(string key)
,但是key
应该是什么并不明显,特别是对于嵌套模型 . 以下是我提出的一些方法来帮助解决这个问题 .RemoveStateFor
方法将采用ModelStateDictionary
,模型和所需属性的表达式,并将其删除 . 通过首先删除其ModelState条目,可以在视图中使用HiddenForModel
来仅使用模型中的值创建隐藏输入字段 . (这可以很容易地扩展为其他帮助扩展方法) .从这样的控制器调用:
或者从这样的观点来看:
它使用
System.Web.Mvc.ExpressionHelper
来获取ModelState属性的名称 .我想更新或重置一个值,如果它没有完全验证,并遇到了这个问题 .
简单的答案,ModelState.Remove,是..有问题..因为如果你使用帮助器,你真的不知道名称(除非你坚持命名约定) . 除非您创建一个自定义帮助程序和控制器都可以用来获取名称的函数 .
此功能应作为帮助程序的一个选项实现,默认情况下不执行此操作,但如果您希望重新显示未接受的输入,则可以这样说 .
但至少我现在理解这个问题;) .
最后得到它 . 我的自定义ModelBinder未注册并执行此操作:
因此默认模型绑定所做的事情必定导致问题 . 不确定是什么,但我的问题至少已经修复,因为我的自定义模型 Binders 正在注册 .
通常,当您发现自己正在与框架标准实践作斗争时,是时候重新考虑您的方法了 . 在这种情况下,ModelState的行为 . 例如,当您在POST后不想要模型状态时,请考虑重定向到get .
编辑回答文化评论:
这是我用来处理多文化MVC应用程序的方法 . 首先是路由处理程序子类:
这是我如何连接路线 . 创建路由后,我会在我的子代理(example.com/subagent1,example.com/subagent2等)之前添加文化代码 . 如果你需要的只是文化,只需从路由处理程序和路由中删除子代理 .