Asp.net mvc Asp.net MVC ModelState.Clear

Asp.net mvc Asp.net MVC ModelState.Clear,asp.net-mvc,modelstate,post-redirect-get,Asp.net Mvc,Modelstate,Post Redirect Get,有谁能给我一个Asp.NETMVC中ModelState角色的简洁定义(或一个链接)。我尤其需要知道在什么情况下调用ModelState.Clear()是必要的或可取的 位开放式huh。。。对不起,我想告诉你我在做什么可能会有帮助: 我在一个名为“页面”的控制器上有一个编辑操作。当我第一次看到更改页面细节的表单时,所有内容都很好地加载(绑定到“MyCmsPage”对象)。然后单击一个按钮,该按钮为MyCmsPage对象的一个字段生成一个值(MyCmsPage.SeoTitle)。它生成fine并

有谁能给我一个Asp.NETMVC中ModelState角色的简洁定义(或一个链接)。我尤其需要知道在什么情况下调用
ModelState.Clear()
是必要的或可取的

位开放式huh。。。对不起,我想告诉你我在做什么可能会有帮助:

我在一个名为“页面”的控制器上有一个编辑操作。当我第一次看到更改页面细节的表单时,所有内容都很好地加载(绑定到“MyCmsPage”对象)。然后单击一个按钮,该按钮为MyCmsPage对象的一个字段生成一个值(
MyCmsPage.SeoTitle
)。它生成fine并更新对象,然后我返回带有新修改的页面对象的操作结果,并期望相关的文本框(使用
呈现)得到更新。。。但遗憾的是,它显示了加载的旧模型的值

我已经通过使用
ModelState.Clear()
解决了这个问题,但我需要知道它为什么/如何工作,这样我就不会盲目地去做

页面控制器:

[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);
 }
<%@ 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>
Aspx:

[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);
 }
<%@ 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>

....
搜索引擎优化标题

更新:

[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);
 }
<%@ 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>
  • 这不是一个bug
  • 请停止从POST操作返回
    View()
    。如果操作成功,请改用并重定向到GET
  • 如果要从POST操作返回
    视图()
    ,请执行表单验证,并使用内置帮助程序进行验证。如果这样做,则不需要使用
    .Clear()
  • 如果您使用此操作返回ajax,请使用webapi控制器并忘记
    ModelState
    ,因为您无论如何都不应该使用它
旧答案:

[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);
 }
<%@ 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>
MVC中的ModelState主要用于描述模型对象的状态,主要与该对象是否有效有关。应该解释很多

通常,您不需要清除ModelState,因为它由MVC引擎为您维护。当试图遵循MVC验证最佳实践时,手动清除它可能会导致不期望的结果


似乎您正在尝试为标题设置默认值。当模型对象在get操作上被实例化(对象本身的某个域层-无参数ctor)时,应该这样做,以便它第一次进入页面或完全在客户端(通过ajax或其他方式)上进入页面,这样它看起来就像是用户输入了它,然后带着发布的表单集合返回。您在接收表单集合时添加此值的方法(在POST action//Edit中)是如何导致这种奇怪行为的,这种行为可能会导致
.Clear()
看起来适合您。相信我,你不会想用透明的。试试其他想法。

模型状态基本上保持了模型在验证方面的当前状态

ModelErrorCollection:表示模型尝试绑定值时的错误。 前

或者像ActionResult中的一个参数

public ActionResult Create(Person person)
ValueProviderResult:保留有关尝试绑定到模型的详细信息。 例如,尝试值、区域性、原始值

必须谨慎使用Clear()方法,因为它可能导致未预测的结果。您将丢失ModelState的一些很好的属性,比如AttemptedValue,MVC在后台使用它来重新填充表单值,以防出错

ModelState["a"].Value.AttemptedValue

我终于明白了。未注册的自定义ModelBinder执行以下操作:

var mymsPage = new MyCmsPage();

NameValueCollection frm = controllerContext.HttpContext.Request.Form;

myCmsPage.SeoTitle = (!String.IsNullOrEmpty(frm["seoTitle"])) ? frm["seoTitle"] : null;

因此,默认模型绑定所做的事情一定是导致问题的原因。不确定是什么,但我的问题至少已经解决了,因为我的自定义模型绑定器正在注册。

如果您想清除单个字段的值,那么我发现以下技术很有用

ModelState.SetModelValue("Key", new ValueProviderResult(null, string.Empty, CultureInfo.InvariantCulture));
注意:
将“Key”更改为要重置的字段的名称。

我认为这是MVC中的一个错误。今天我为这个问题挣扎了几个小时

鉴于此:

public ViewResult SomeAction(SomeModel model) 
{
    model.SomeString = "some value";
    return View(model); 
}
视图将使用原始模型进行渲染,忽略更改。所以我想,也许它不喜欢我使用相同的模型,所以我试着这样做:

public ViewResult SomeAction(SomeModel model) 
{
    var newModel = new SomeModel { SomeString = "some value" };
    return View(newModel); 
}
ModelState.RemoveStateFor(model, m => m.MySubProperty.MySubValue);
@Html.HiddenForModel(m => m.MySubProperty.MySubValue)
并且视图仍然使用原始模型进行渲染。奇怪的是,当我在视图中放置断点并检查模型时,它的值已更改。但是响应流具有旧的值

最终我发现了和你一样的工作:

public ViewResult SomeAction(SomeModel model) 
{
    var newModel = new SomeModel { SomeString = "some value" };
    ModelState.Clear();
    return View(newModel); 
}
一切正常


我不认为这是一个“功能”,是吗?

我有一个例子,我想更新sumitted表单的模型,但出于性能原因不想“重定向到操作”。以前隐藏字段的值被保留在我更新的模型上-导致各种各样的问题

几行代码很快确定了ModelState中我想要删除的元素(在验证之后),因此在表单中使用了新值:-

while (ModelState.FirstOrDefault(ms => ms.Key.ToString().StartsWith("SearchResult")).Value != null)
{
    ModelState.Remove(ModelState.FirstOrDefault(ms => ms.Key.ToString().StartsWith("SearchResult")));
}

我想更新或重置一个没有完全验证的值,但遇到了这个问题

简单的答案是,ModelState.Remove是。。有问题的因为如果您使用的是helpers,您并不真正知道它的名称(除非您遵守命名约定)。除非您创建了一个自定义助手和控制器都可以用来获取名称的函数

这个特性应该作为帮助器上的一个选项实现,默认情况下是不这样做,但是如果您希望重新显示未接受的输入,您可以这样说


但至少我现在理解了这个问题;)

通常,当您发现自己在与框架标准实践作斗争时,是时候重新考虑您的方法了。在本例中,ModelState的行为。例如,当您不想在采购订单后显示模型状态时