gpt4 book ai didi

asp.net-mvc - 在 EditorFor 中用于子对象时,MVC 无法覆盖 EditorTemplate 名称

转载 作者:行者123 更新时间:2023-12-04 02:50:25 24 4
gpt4 key购买 nike

我正在尝试使用 EditorTemplate 在父 View 的表中显示子集合。我遇到的问题是,这似乎只有在模板的名称与子类的名称完全相同时才有效。当我尝试使用名称略有不同的模板,并将该名称作为 templateName 参数传递给 EditorFor 时,出现运行时错误。我希望我可以将不同的子 EditorTemplates 用于相同的子集合的不同目的。
下面是一个简短的例子:

型号:

public class Customer
{
int id { get; set; }
public string name { get; set; }

public List<Order> Orders { get; set; }
}
public class Order
{
public int id { get; set; }
public DateTime orderdate { get; set; }
public decimal amount { get; set; }

public Customer customer { get; set; }
}

客户 Controller Index() 方法:
public ActionResult Index()
{
Customer customer = new Customer() {id = 1, name = "Acme Corp.", Orders = new List<Order>()};
customer.Orders.Add(new Order() {id = 1, orderdate = DateTime.Now, amount = 100M});
customer.Orders.Add(new Order() { id = 2, orderdate = DateTime.Now, amount = 200M });
return View(customer);
}

客户索引.cshtml View :
@model TemplateTest.Customer

@{
Layout = null;
}

<!DOCTYPE html>

<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Customer</title>
</head>
<body>
<div>
@Html.EditorFor(Model=>Model.name)

<table>
<thead>
<tr>
<th>Order ID</th>
<th>Order Date</th>
<th>Amount</th>
</tr>
</thead>
@Html.EditorFor(Model=>Model.Orders)
</table>

</div>
</body>
</html>

Views/Shared/EditorTemplates 中的 Order.cshmtl 模板 (添加了“颜色”以验证我正在使用此模板):
@model TemplateTest.Order

<tr>
<td>@Html.DisplayFor(Model=>Model.id)</td>
<td style="color:blue">@Html.EditorFor(Model=>Model.orderdate)</td>
<td>@Html.EditorFor(Model=>Model.amount)</td>
</tr>

这工作正常。但是,如果我将 EditorTemplate 重命名为“OrderList.cshtml”并将子 EditorFor 行更改为
@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 默认模板,但这一点都不明显。

试着这样想:

在工作版本中,您传入一个类型 List<Order>引用 Model.Orders (许多订单)但模板指定的型号为 Order (单个,不多)。

有趣。为什么这甚至有效?乍一看似乎应该 不是 工作。但它确实有效,因为幕后发生的事情。

转述自上述帖子:

When you use @Html.EditorFor(c => c.Orders) MVC convention chooses the default template for IEnumerable. This template is part of the MVC framework, and what it does is generate Html.EditorFor() 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, so, the Order template is used for each item.



这就是魔法,它很方便,但因为这是按惯例发生的并且基本上对我们隐藏,所以我认为这是混淆的根源。

现在,当您尝试通过显式设置 EditorFor 使用命名模板执行相同操作时使用特定的编辑器模板 OrderList ,您最终会通过整个枚举传递该编辑器模板 - 这就是您发布的错误的来源。

换句话说,失败的案例设法跳过了工作案例的“神奇”部分,这就是它失败的原因。但是,从语义上看,它看起来不错,听起来不错,对吧?有困惑。

工作案例:
your call                                default MVC template      your template
@Html.EditorFor( Model => Model.Orders) IEnumerable template Order template

失败案例:
your call                                           your template
@Html.EditorFor(Model=>Model.Orders, "OrderList") OrderList template ERROR!!!

有多种方法可以消除错误,但其中许多方法都有问题,因为它们会导致 HTML 控件的呈现方式使您无法通过 POST 上的索引来寻址各个控件。呃。 (注意:工作案例确实按预期正确呈现 HTML)

要正确呈现 HTML 控件,您似乎必须使用常规 for循环(不是 foreach )并传递每个 Order对象到自定义模板(我称之为 OrderEditorTemplateDefault)。
@for (int i = 0; i < Model.Orders.Count ; i++) 
{
@Html.EditorFor(c => Model.Orders[i], "OrderEditorTemplateDefault")
}

您的部分问题指出:

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



您可以通过在循环内引入一个条件并在那里选择备用模板来做到这一点(对于整个列表或按订单排序,仅取决于您如何编写条件)
@for (int i = 0; i < Model.Orders.Count ; i++) {
if (someCondition) {
@Html.EditorFor(c => Model.Orders[i], "OrderEditorTemplateDefault")
} else {
@Html.EditorFor(c => Model.Orders[i], "OrderEditorTemplateALTERNATE")
}
}

抱歉这么啰嗦。希望有帮助。

关于asp.net-mvc - 在 EditorFor 中用于子对象时,MVC 无法覆盖 EditorTemplate 名称,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16629763/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com