asp.net-mvc – 在EditorFor for child对象中使用时,MVC无法覆盖EditorTemplate的名称

前端之家收集整理的这篇文章主要介绍了asp.net-mvc – 在EditorFor for child对象中使用时,MVC无法覆盖EditorTemplate的名称前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我试图使用EditorTemplate在父视图中的表中显示一个子集合.我遇到的问题是,如果模板的命名与孩子的类完全相同,这只会起作用.当我尝试使用稍有不同名称的模板,并将该名称作为TemplateFor参数传递给EditorFor时,会收到运行时错误.我希望我可以使用不同的孩子EditorTemplates与不同的目的与同一个孩子集合.
这是一个简短的例子:

楷模:

  1. public class Customer
  2. {
  3. int id { get; set; }
  4. public string name { get; set; }
  5.  
  6. public List<Order> Orders { get; set; }
  7. }
  8. public class Order
  9. {
  10. public int id { get; set; }
  11. public DateTime orderdate { get; set; }
  12. public decimal amount { get; set; }
  13.  
  14. public Customer customer { get; set; }
  15. }

客户控制器Index()方法

  1. public ActionResult Index()
  2. {
  3. Customer customer = new Customer() {id = 1,name = "Acme Corp.",Orders = new List<Order>()};
  4. customer.Orders.Add(new Order() {id = 1,orderdate = DateTime.Now,amount = 100M});
  5. customer.Orders.Add(new Order() { id = 2,amount = 200M });
  6. return View(customer);
  7. }

客户Index.cshtml视图:

  1. @model TemplateTest.Customer
  2.  
  3. @{
  4. Layout = null;
  5. }
  6.  
  7. <!DOCTYPE html>
  8.  
  9. <html>
  10. <head>
  11. <Meta name="viewport" content="width=device-width" />
  12. <title>Customer</title>
  13. </head>
  14. <body>
  15. <div>
  16. @Html.EditorFor(Model=>Model.name)
  17.  
  18. <table>
  19. <thead>
  20. <tr>
  21. <th>Order ID</th>
  22. <th>Order Date</th>
  23. <th>Amount</th>
  24. </tr>
  25. </thead>
  26. @Html.EditorFor(Model=>Model.Orders)
  27. </table>
  28.  
  29. </div>
  30. </body>
  31. </html>

在View / Shared / EditorTemplates中添加了Order.cshmtl模板(添加了“color”来验证我正在使用此模板):

  1. @model TemplateTest.Order
  2.  
  3. <tr>
  4. <td>@Html.DisplayFor(Model=>Model.id)</td>
  5. <td style="color:blue">@Html.EditorFor(Model=>Model.orderdate)</td>
  6. <td>@Html.EditorFor(Model=>Model.amount)</td>
  7. </tr>

这工作正常但是,如果我将EditorTemplate重命名为“OrderList.cshtml”,并将小孩EditorFor行更改为

  1. @Html.EditorFor(Model=>Model.Orders,"OrderList")

当我再次运行它,我得到这个例外:

“传入字典的模型项目的类型为”System.Collections.Generic.List“1 [TemplateTest.Order]”,但是这个字典需要一个类型为“TemplateTest.Order”的模型项.

任何想法为什么EditorFor不使用我在“templateName”参数中指定的模板“OrderList”?否则,该参数是什么?

解决方法

TL;DR > Named templates don’t work with collections,use a foreach loop to work around it – See below for extensive details about why,and an example.

你说:

Any idea why the EditorFor doesn’t use the template “OrderList” I
specified in the “templateName” argument? Otherwise,what is that
argument for?

EditorFor实际上是使用你指定的模板OrderList,但是你已经偶然发现了一些令人困惑的事情.一些研究提出了很多提示,但是我在这篇文章中发现了真正的坚果和细节:Problem with MVC EditorFor named template

简而言之,发生的是默认的情况:@ Html.EditorFor(Model => Model.Orders)实际上是按照惯例在临时调用MVC默认模板,但这根本不是很明显.

尝试这样思考:

在工作版本中,您将传递一个类型列表< Order>参考Model.Orders(MANY orders),但模板是用Order(single,NOT MANY)模型指定的.

有趣.为甚么甚至工作?乍看起来好像不行.但是,由于幕后发生了什么,它确实有效.

从上述帖子改写:

When you use @Html.EditorFor(c => c.Orders)@H_403_60@ MVC convention chooses
the default template for IEnumerable@H_403_60@. This template is part of the MVC framework,and what it does is generate Html.EditorFor()@H_403_60@ for
each item in the enumeration. That template then generates the
appropriate editor template for each item in the list individually
– in your case they’re all instances of Order@H_403_60@,so,the Order@H_403_60@ template is used for each item.

这是魔法,它是方便的,但是因为这是惯例发生的,并且基本上是我们隐藏的,所以我认为是混乱的根源.

现在当你尝试做同样的事情,但使用一个命名的模板,通过显式设置你的EditorFor来使用一个特定的编辑器模板OrderList,你最终会传递整个枚举的编辑器模板 – 这是错误的根源发布.

换句话说,失败的案例设法跳过工作案例的“魔法”部分,这就是为什么它失败.但是,在语义上它看起来很好听,对吧?有混乱.

工作情况:

  1. your call default MVC template your template
  2. @Html.EditorFor( Model => Model.Orders) IEnumerable template Order template

失败案件:

  1. your call your template
  2. @Html.EditorFor(Model=>Model.Orders,"OrderList") OrderList template ERROR!!!

有很多方法可以使错误消失,但是其中许多方法是有问题的,因为它们导致HTML控件的渲染方式阻止您通过POST上的索引来处理单个控件. Uhhg. (注意:工作案例确实按原样正确呈现HTML)

为了正确渲染HTML控件,您似乎必须使用常规for循环(而不是foreach),并将每个单独的Order对象传递给自定义模板(我称之为OrderEditorTemplateDefault).

  1. @for (int i = 0; i < Model.Orders.Count ; i++)
  2. {
  3. @Html.EditorFor(c => Model.Orders[i],"OrderEditorTemplateDefault")
  4. }

部分你的问题表示:

I was hoping I could use different child EditorTemplates for different
purposes with the same child collection.

您可以通过在循环中引入条件并在其中选择替代模板(无论是对于整个列表还是按顺序排列,仅取决于如何编写条件)

  1. @for (int i = 0; i < Model.Orders.Count ; i++) {
  2. if (someCondition) {
  3. @Html.EditorFor(c => Model.Orders[i],"OrderEditorTemplateDefault")
  4. } else {
  5. @Html.EditorFor(c => Model.Orders[i],"OrderEditorTemplateALTERNATE")
  6. }
  7. }

对不起这么冗长希望有帮助.

猜你在找的asp.Net相关文章