【问题标题】:ASP.Net MVC ModelState / Html.TextBox postback issueASP.Net MVC ModelState / Html.TextBox 回发问题
【发布时间】:2009-05-07 14:05:48
【问题描述】:

我在尝试发布的表单中突然出现问题。在表单不验证的情况下,我采用调用ModelState.AddModelError() 然后返回查看结果的标准路线。

问题是,HTML.* 助手应该在渲染时获取发布的值,我注意到我的文本字段只有在我将它们包含在回发操作的参数列表中时才会这样做,这应该'不需要,因为某些表单有太多字段,无法将它们全部列为参数。

我的动作代码大致是:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult EditDataDefinition(long? id, string name)
{
    var dataDefinition = ...

    // do some validation stuff
    if (!ModelState.IsValid)
    {
        // manually set checkbox fields via ViewData seeing as this STILL doesn't work in MC 1.0 :P
        // ...
        return View(dataDefinition);
    }

}

现在,dataDefinition(它是一个 LINQ to SQL 实体)有一个字段 MinVolume,在视图中由以下行处理:

Minimum: <%= Html.TextBox("MinVolume", null, new { size = 5 })%>

然而,当在 ModelState 验证失败后呈现视图时,在我们发布的原始页面上键入的值不会保留,除非我将其作为参数包含在回发方法中。从字面上看,我可以通过这样做“解决问题”:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult EditDataDefinition(long? id, string name, string minVolume)

出于某种原因,这将强制保留字段值。这对我来说似乎很愚蠢,因为我的表单具有比这更多的值,我不应该只为该字段添加参数。

有什么想法吗?

【问题讨论】:

    标签: c# asp.net-mvc html-helper


    【解决方案1】:

    天哪,我刚刚改进了我的应用程序设计。 出现问题是因为您有自定义验证(我也有)。 你必须在之后添加

    ModelState.AddModelError()
    

    这个

    ModelState.SetModelValue("MinVolume", ValueProvider["MinVolume"]);
    

    在视图中它必须是

    Mimum:<%=Html.Textbox("MinVolume")%>
    

    仍然不确定它为什么有效,但它对我有用。

    【讨论】:

    • 哦...这可能是答案!我早上上班时会检查。谢谢。
    • 之所以有效,是因为它将值添加到模型中,帮助器从中提取值。使用 UpdateModel 也可以,我使用的是什么以及为什么要保留我的文本框值。
    【解决方案2】:

    可能是你的代码:

    <%= Html.TextBox("MinVolume", null, new { size = 5 })%>
    

    ..默认值参数有null 吗?也许如果您将null 更改为Model.MinVolume,它将保留该值。像这样:

    <%= Html.TextBox("MinVolume", Model.MinVolume, new { size = 5 })%>
    

    我不确定您的操作是否在模型中返回值 MinVolume。如果是这样,上述应该工作。否则,您可能需要稍微重构操作。

    【讨论】:

    • 不,指定 null 应该指定应该使用现有模型上下文来查询值。指定 MinVolume 是明确的,并且会强制使用该值而不是之前提交的值。
    • 不正确。指定 MinVolume 会查找 ViewDataDoctionary,然后查找 ModelStateDictionary 以查找后续帖子。因此,如果 Model.MinVolume 说 5 becore edit,那么指定 MinVolume 会将 5 放入 TextBox。然后,如果发布了帖子(例如值 3)但发现无效,则 TextBox 将在第二轮显示 3。你试过了吗?您通常在“新建”或“创建”视图上指定 null,以便初始帖子在字段中显示为空,而后续帖子会保留输入的值。
    • 这正是我的做法,而且每次都有效。我从来没有见过你必须指定 null 的地方。一个指向你看到的地方的链接会很好。
    【解决方案3】:

    当您在 ModelState 中设置错误值时,您使用的是什么键?为 TextBox 设置 value 参数的代码如下所示:

    downloaded framework code 的相关部分。

    string attemptedValue = (string)htmlHelper.GetModelStateValue(name, typeof(string));
    tagBuilder.MergeAttribute("value", attemptedValue ?? ((useViewData) ? htmlHelper.EvalString(name) : valueParameter), isExplicitValue);
    

    如您所见,如果尝试值存在,它将使用它——但前提是相同的键可用。

    我知道这是可行的,因为我有一个不带参数并直接从 ValueProvider 获取值的操作,它使用 AddModelError 来指示验证错误。我确定我的 TextBoxes 中的值被保留了。

    编辑:为了保留这些值,它们需要以某种方式与模型相关联。一种方法是将它们添加到参数列表中。另一种方法是使用 UpdateModel(参数名称在白名单中或没有白名单)。第三种方法是将参数显式添加到模型中,如@Jenea 的回答。由于助手只从模型状态中提取,它们必须在那里才能保留值。它不查看请求的 Form 属性。

    【讨论】:

    • 该字段根本没有经过验证——它不需要在这个阶段。因此,它只是表单中的“无辜旁观者”,如果其他字段之一不正常运行并因此导致表单再次呈现,则希望保留其新值。
    • 我突然想知道我是否错误地假设 ModelState 应该尝试保留名称与模型匹配的所有字段。也许它只保留通过参数列表传入或通过 AddModelError 引用的字段?如果是这样的话,这似乎有点愚蠢,因为我当然想保留表格中的所有内容,而不仅仅是特定案例。话又说回来,MVC 仍然无法正确保留复选框字段...
    【解决方案4】:

    据我了解,解决方案是:

    [Transaction]
    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult EditDataDefinition(int id, FormCollection form)
    {
        T itemToUpdate = repository.Get(id);
        UpdateModel(itemToUpdate, form.ToValueProvider());
    
        if (itemToUpdate.IsValid())
        {
            repository.SaveOrUpdate(itemToUpdate);
            return Json(ValidationResultToJson(itemToUpdate.ValidationResults()));
        }
    
        repository.DbContext.RollbackTransaction();
        return Json(ValidationResultToJson(itemToUpdate.ValidationResults()));
    }
    

    祝你好运!

    【讨论】:

      【解决方案5】:

      另一种解决方案是在视图中输入:

      <%var minVolume=Request["MinVolume"]??"";%>
      <%=Html.Textbox("MinVolume",minVolume,new {size=5})%>
      

      【讨论】:

        【解决方案6】:

        请参阅本文了解在 ASP.NET MVC 中处理回发的不同方法

        link text

        【讨论】:

        • 不错的入门文章。
        猜你喜欢
        • 2011-02-04
        • 2023-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多