使用在ASP.NET MVC的IEnumerable车型自定义编辑器模板正确的,地道的表达方式 [英] Correct, idiomatic way to use custom editor templates with IEnumerable models in ASP.NET MVC

查看:174
本文介绍了使用在ASP.NET MVC的IEnumerable车型自定义编辑器模板正确的,地道的表达方式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个问题是一个后续的为什么我DisplayFor通过我的IEnumerable&LT不循环; DateTime的>

一个快速刷新。


  • 的模型类型的属性的IEnumerable< T>

  • 您通过这个属性 Html.EditorFor()使用只接受拉姆达前pression过载

  • 您有次下的类型 T 编辑模板/共享/ EditorTemplates

  • the model has a property of type IEnumerable<T>
  • you pass this property to Html.EditorFor() using the overload that only accepts the lambda expression
  • you have an editor template for the type T under Views/Shared/EditorTemplates

然后对MVC引擎将自动调用在枚举序列中的每个项目的编辑模板,产生的结果的列表。

then the MVC engine will automatically invoke the editor template for each item in the enumerable sequence, producing a list of the results.

例如,当有一个模型类订单财产

E.g., when there is a model class Order with property Lines:

public class Order
{
    public IEnumerable<OrderLine> Lines { get; set; }
}

public class OrderLine
{
    public string Prop1 { get; set; }
    public int Prop2 { get; set; }
}

和有一种观点查看/共享/ EditorTemplates / OrderLine.cshtml:

And there is a view Views/Shared/EditorTemplates/OrderLine.cshtml:

@model TestEditorFor.Models.OrderLine

@Html.EditorFor(m => m.Prop1)
@Html.EditorFor(m => m.Prop2)

然后,当你调用 @ Html.EditorFor(M = GT; m.Lines)从顶级视图,您将获得使用文本框的页面每个订单行,不只是一个。

Then, when you invoke @Html.EditorFor(m => m.Lines) from the top-level view, you will get a page with text boxes for each order line, not just one.

然而,正如你可以在链接的问题看,这只有当您使用作品的 EditorFor 特别超载。如果你提供一个模板名称(以便使用该订单行类后未命名模板),然后自动顺序处理不会发生,并且运行时错误会而不是发生了。

However, as you can see in the linked question, this only works when you use that particular overload of EditorFor. If you provide a template name (in order to use a template that is not named after the OrderLine class), then the automatic sequence handling will not happen, and a runtime error will happen instead.

在这一点上,你必须声明你的自定义模板的模型 IEnumebrable&LT;订单行&GT; 并手动遍历其项目以某种方式或其他输出所有的人,例如:

At which point you will have to declare your custom template's model as IEnumebrable<OrderLine> and manually iterate over its items in some way or another to output all of them, e.g.

@foreach (var line in Model.Lines) {
    @Html.EditorFor(m => line)
}

而这正是问题的开始。

And that is where problems begin.

在这种方式,所有生成的HTML控件具有相同的ID和名称。当你以后它们张贴,模型绑定就无法构建的订单行秒的数组,模型对象,你在控制器将是HttpPost方法来获得。结果
这是有道理的,如果你看一下拉姆达前pression - 它并没有真正链接对象正在建设中所来自模型的地方

The HTML controls generated in this way all have same ids and names. When you later POST them, the model binder will not be able to construct an array of OrderLines, and the model object you get in the HttpPost method in the controller will be null.
This makes sense if you look at the lambda expression - it does not really link the object being constructed to a place in the model from which it comes.

我试图遍历的项目不同方法,它似乎是唯一的办法就是重新定义模板的模型的IList&LT; T&GT; 和<枚举它code>为:

I have tried various ways of iterating over the items, and it would seem the only way is to redeclare the template's model as IList<T> and enumerate it with for:

@model IList<OrderLine>

@for (int i = 0; i < Model.Count(); i++)
{ 
    @Html.EditorFor(m => m[i].Prop1)
    @Html.EditorFor(m => m[i].Prop2)
}

然后在顶层的看法:

Then in the top-level view:

@model TestEditorFor.Models.Order

@using (Html.BeginForm()) {
    @Html.EditorFor(m => m.Lines, "CustomTemplateName")
}

,它给出了正确的模型绑定上公认的正确命名的HTML控件的提交。

which gives properly named HTML controls that are properly recognized by the model binder on a submit.

虽然这个作品,感觉非常错误的。

While this works, it feels very wrong.

什么是使用与 EditorFor 自定义编辑模板,而preserving所有逻辑链接,使发动机能够产生正确的,地道的表达方式HTML适合模型绑定?

What is the correct, idiomatic way to use a custom editor template with EditorFor, while preserving all the logical links that allow the engine to generate HTML suitable for the model binder?

推荐答案

与埃里克Funkenbusch ,这导致经过讨论寻找到<一个href=\"https://aspnetwebstack.$c$cplex.com/SourceControl/latest#src/System.Web.Mvc/Html/DefaultEditorTemplates.cs\">MVC来源$ C ​​$ C ,似乎有两个更好的(正确的,地道?)的方式来做到这一点。

After discussion with Erik Funkenbusch, which led to looking into the MVC source code, it would appear there are two nicer (correct and idiomatic?) ways to do it.

两者都涉及到助手提供正确的HTML名称preFIX,并生成HTML等同于默认的输出 EditorFor

Both involve providing correct html name prefix to the helper, and generate HTML identical to the output of the default EditorFor.

我就离开这里,现在,会做更多的测试,以确保它在嵌套很深的场景。

I'll just leave it here for now, will do more testing to make sure it works in deeply nested scenarios.

对于下面的例子,假设你已经有订单行两个模板类: OrderLine.cshtml DifferentOrderLine.cshtml

For the following examples, suppose you already have two templates for OrderLine class: OrderLine.cshtml and DifferentOrderLine.cshtml.

创建一个辅助模板,以任何名义(如ManyDifferentOrderLines.cshtml),它保存:

Create a helper template, saving it under any name (e.g. "ManyDifferentOrderLines.cshtml"):

@model IEnumerable<OrderLine>

@{
    int i = 0;

    foreach (var line in Model)
    { 
        @Html.EditorFor(m => line, "DifferentOrderLine", "[" + i++ + "]")
    }
}

然后从主订单模板调用它:

Then call it from the main Order template:

@model Order

@Html.EditorFor(m => m.Lines, "ManyDifferentOrderLines")


方法2 - 如果不为的IEnumerable℃的中间模板; T&GT;

在主订单模板:


Method 2 - Without an intermediate template for IEnumerable<T>

In the main Order template:

@model Order

@{
    int i = 0;

    foreach (var line in Model.Lines)
    {
        @Html.EditorFor(m => line, "DifferentOrderLine", "Lines[" + i++ + "]")
    }
}

这篇关于使用在ASP.NET MVC的IEnumerable车型自定义编辑器模板正确的,地道的表达方式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆