MVC3非顺序索引和DefaultModelBinder

min*_*ods 41 defaultmodelbinder modelbinders asp.net-mvc-3

MVC 3.0中的默认模型绑定器是否能够处理非顺序索引(对于简单和复杂模型类型)?我遇到的帖子表明应该这样做,但是在我的测试中它似乎没有.

给出后期值:

items[0].Id = 10
items[0].Name = "Some Item"
items[1].Id = 3
items[1].Name = "Some Item"
items[4].Id = 6
items[4].Name = "Some Item"
Run Code Online (Sandbox Code Playgroud)

和控制器方法:

public ActionResult(IList<MyItem> items) { ... }
Run Code Online (Sandbox Code Playgroud)

加载的唯一值是项0和1; 第4项被忽略了.

我已经看到了许多生成自定义索引的解决方案(模型绑定到列表),但是它们似乎都是针对MVC的早期版本,而且大多数都是有点"严厉"的IMO.

我错过了什么吗?

Bas*_*nni 70

我有这个工作,您必须记住添加一个常见的索引隐藏输入,如您引用的文章中所述:

隐藏的输入name = Items.Index是关键部分

<input type="hidden" name="Items.Index" value="0" />
<input type="text" name="Items[0].Name" value="someValue1" />

<input type="hidden" name="Items.Index" value="1" />
<input type="text" name="Items[1].Name" value="someValue2" />

<input type="hidden" name="Items.Index" value="3" />
<input type="text" name="Items[3].Name" value="someValue3" />

<input type="hidden" name="Items.Index" value="4" />
<input type="text" name="Items[4].Name" value="someValue4" />
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助

  • 哦,我的努力!这使得返回列表变得更容易,而不是为(i ++)做荒谬我只能使用索引上的主键或任何其他ID,并且列表返回如此好,并且强类型.这些黑暗,隐藏的秘密.这让我很快乐!+1 +啤酒!!! (4认同)

dan*_*wig 6

您引用的文章是一篇旧文章(MVC2),但据我所知,这仍然是使用默认模型绑定器对绑定集合进行建模的事实上的方法。

如果您想要非顺序索引,就像巴萨姆所说,您将需要指定一个索引器。索引器不需要是数字。

为此,我们使用Steve Sanderson 的 BeginCollectionItem Html Helper 。它会自动生成索引器作为 Guid。我认为当您的集合项 HTML 是非顺序的时,这是比使用数字索引器更好的方法。


Phi*_*rdt 5

这个辅助方法源于Steve Sanderson的方法,它更加简单,可用于锚定集合中的任何项目,它似乎与MVC模型绑定一起使用.

public static IHtmlString AnchorIndex(this HtmlHelper html)
{
    var htmlFieldPrefix = html.ViewData.TemplateInfo.HtmlFieldPrefix;
    var m = Regex.Match(htmlFieldPrefix, @"([\w]+)\[([\w]*)\]");
    if (m.Success && m.Groups.Count == 3)
        return
            MvcHtmlString.Create(
                string.Format(
                    "<input type=\"hidden\" name=\"{0}.index\" autocomplete=\"off\" value=\"{1}\" />",
                    m.Groups[1].Value, m.Groups[2].Value));
    return null;
}
Run Code Online (Sandbox Code Playgroud)

例如,只需在EditorTemplate或您将生成输入的任何其他位置调用它,如下所示,以生成索引锚定隐藏变量(如果适用).

@model SomeViewModel
@Html.AnchorIndex()
@Html.TextBoxFor(m => m.Name)
... etc.
Run Code Online (Sandbox Code Playgroud)

我认为它比史蒂夫桑德森的方法有一些优势.

  1. 它适用于EditorFor和其他内置机制来处理枚举.因此,如果ItemsIEnumerable<T>视图模型上的属性,则以下按预期工作:

    <ul id="editorRows" class="list-unstyled"> @Html.EditorFor(m => m.Items) @* Each item will correctly anchor allowing for dynamic add/deletion via Javascript *@ </ul>

  2. 它更简单,不需要任何魔术字符串.

  3. 对于数据类型,您可以使用单个EditorTemplate/DisplayTemplate,如果未在列表中的项目上使用,则它将只是无操作.

唯一的缺点是,如果绑定的根模型是可枚举的(即Action方法本身的参数,而不仅仅是参数对象图中更深处的属性),则绑定将在第一个非顺序索引处失败.不幸的是,.IndexDefaultModelBinder 的功能仅适用于非root对象.在这种情况下,您唯一的选择仍然是使用上述方法.