ModelState绑定自定义数组的复选框

时间:2014-01-03 17:24:41

标签: asp.net-mvc modelstate html.checkbox

ViewModel Binding正在运行,传回编辑控制器的对象包含正确的值,这是一个选定选项的列表。但是, ModelState绑定无法正常工作,模型状态AttemptedValues存在,但未重新加载到字段中。

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

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

但在我看来,我有一些分类,所以我不能做直接的预告。

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,但它没有自动绑定,因为我有一个自定义字段用于复选框。

这段代码很臭

是否有更好的方法从Attempted Value

加载数据

编辑:

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

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

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

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

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

是否有更好的方法可以从模型状态的“尝试值”中加载数据。

2 个答案:

答案 0 :(得分:1)

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

您应该在控制器中计算并生成视图所需的所有数据,然后使用Controller将这些数据传递到视图(看起来您已经这样做了),您也可以使用{ {1}}传递模型中未包含的其他数据。然后视图负责生成HTML。

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

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

您可以阅读有关将数据传递到视图here的更多信息。

答案 1 :(得分:0)

好的,基本上,我找不到任何可以帮我的东西。默认的Html帮助器方法不包括这种情况。

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

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

最终看起来像这样。

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

该方法执行以下操作

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

    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);
    }
    
相关问题