-1

ViewModel 绑定工作,传回编辑控制器的对象包含正确的值,这是一个选定选项的列表。但是,ModelState 绑定不起作用,模型状态 AttemptedValues 存在,但没有被重新加载到字段中。

我有一个具有以下属性的模型

class Model
{
    public List<string> AvailableValues { get; set; }
    public List<string> SelectedValues { get; set; }
}

但在我看来,我有一些分类,所以我不能直接进行 foreach。

foreach (var category in CatgoryList.Categories)
{
    foreach (var available in Model.AvailableValues.Where(x => category.AvailableValues.Contains(x))
    {
        var check = Model.SelectedValues!= null && Model.SelectedValues.Contains(available.Id);
        check &= (ViewData.ModelState["SelectedValues"] != null) && ViewData.ModelState["SelectedValues"].Value.AttemptedValue.Contains(available.Id);
        <input type="checkbox" name="SelectedValues" id="available.Id" value="available.Id" checked="@check"/>@available.FriendlyName<br>
    }
}

ModelState 确实包含上一篇文章中的 SelectedValues,但它不会自动绑定,因为我有一个用于复选框的自定义字段。

这段代码很臭

有没有更好的方法来从尝试值加载数据

编辑:

好的,所以我的问题不够清楚,让我澄清一下。

在验证时,如果出现错误,我将重新调整相同的视图。modelstate 保存先前在 ModelState["field"].Value.AttemptedValue 中输入的值。对于使用帮助器、TextboxFor、CheckboxFor 等创建的字段,这些值会自动填充。

但是,当使用普通反射进行复选框绑定时,只有选中复选框的值会在传递回控制器的数据对象中返回。这意味着我没有使用从 ModelState 中填充值的逻辑。

我所做的是自己挖掘模型状态以获取尝试的值,因为它们确实存在于字段名称“SelectedValues”下。但我必须手动应用它们。那里的值看起来像这样。

ModelState["SelectedValues"] = "Value1;Value2;Value4"

有没有更好的方法来从模型状态中的尝试值加载数据。

4

2 回答 2

1

我在这里看到的主要“气味”(使用您的术语)是嵌套 foreach 中的代码直接写在您的视图中(* .cshtml),但这种复杂性的代码应该在您的Controller操作中。

Model您应该在控制器中计算并生成视图所需的所有数据,然后使用(看起来您已经在这样做)将该数据传递给视图,您还可以使用ViewBag传递未包含在模型中的其他数据. 然后视图只负责生成 HTML。

这是我在您的代码中看到的另一个问题 - 您正在引用ViewData.ModelState在视图中看到的非常不寻常的问题。在决定渲染哪个视图之前,应该在控制器中检查 ModelState。

看起来您可能只是通过 ViewData.ModelState 传递数据,而实际上应该通过 ViewData/ViewBag 传递数据。

您可以在此处阅读有关将数据传递给视图的更多信息。

于 2014-01-04T11:57:00.130 回答
0

好的,所以基本上,我找不到任何可以为我做这件事的东西。默认的 Html 辅助方法只是不涵盖这种情况。

所以,我写了一个扩展方法。

基本上,它使用您发送给它的表达式从模型中提取枚举器,就像任何其他帮助器一样,但您也发送列表中要构建复选框的条目。

它最终看起来像这样。

@Html.CheckboxListEntryFor(x => x.SelectedEntries, AvailableEntries[i].Id)

该方法执行以下操作

  1. 获取列表的 propertyInfo 并检查所选条目是否包含这些值。
  2. 检查ModelState是否无效,如果是,用modelstate条目覆盖检查的值
  3. 构建一个html复选框,使用属性名称作为复选框的名称和id,并根据前面的步骤设置checked。

    public static MvcHtmlString CheckboxListEntryFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper,
        Expression<Func<TModel, TProperty>> expression, string entryValue)
    {
        PropertyInfo info = GetPropertyInfo(typeof (TModel), expression);
        var enumerator = info.GetValue(htmlHelper.ViewData.Model);
        var check = enumerator != null && ((IList) enumerator).Contains(entryValue);
        if (!htmlHelper.ViewData.ModelState.IsValid)
        {
            check = htmlHelper.ViewData.ModelState[info.Name] != null &&
                htmlHelper.ViewData.ModelState[info.Name].Value.AttemptedValue.Contains(entryValue);
        }
    
        var fieldString = String.Format(
                          "<input type=\"checkbox\" name=\"{0}\" id =\"{1}\" value=\"{1}\"{2}/>",
                          info.Name, entryValue, check ? " checked=\"checked\"" : string.Empty);
    
        return MvcHtmlString.Create(fieldString);
    }
    
于 2014-01-06T20:50:20.893 回答