正在尝试将ICollection添加到ASP.NET中的ViewModel中
本文关键字:NET ASP 中的 ViewModel 添加 ICollection | 更新日期: 2023-09-27 18:28:33
我看过这篇文章,那里的小伙子似乎想做我想要做的事情。我继承了这个应用程序,尽管我是一名.NET开发人员,但与我喜欢的其他语言中的其他MVC框架相比,MVC的东西似乎很神奇。我的显著代码如下:
public class PurchaseOrderViewModel
{
public PurchaseOrderViewModel()
{
this.PurchaseOrder = new PurchaseOrder();
}
// Some other fields here....
public PurchaseOrder PurchaseOrder { get; set; }
public IList<PurchaseOrderItem> OrderItems { get; set; }
}
控制器:
[HttpPost]
public ActionResult Details(PurchaseOrderViewModel viewModel)
{
// bunch of stuff. the viewModels.OrderItems here is null.
}
模型中的OrderItems是一个ICollection<>我正在转换为迭代性质的IList。该观点的相关部分如下:
@model PurchaseOrderViewModel
@for (var i = 0; i < this.Model.OrderItems.Count; i++)
{
@Html.EditorFor(m => m.OrderItems[i].Quantity);
}
那么,为什么我没有通过OrderItems呢?这是因为它们是IList而不是ICollection吗?如果是,解决方法是什么?
编辑:我已经更改了视图代码,因为我在中留下了以前尝试过的内容。
编辑2:我考虑了当前的评论/答案,所以现在我做了以下更改:
视图模型:
public ICollection<PurchaseOrderItem> PurchaseOrderItems { get; set; }
PurchaseOrderItem.cshtml:(我把它留在代码中,以防万一):
@model Downland.Model.PurchaseOrderItem
<tr style="background-color: #fff; padding: 8px;">
<td style="text-align: left; width: 210px;">
@if (this.Model.ProductID == null)
{
<img class="viewproduct" src="~/Images/GetThumbnail/-1" alt="Product Image" style="padding: 8px;" />
}
else
{
<img class="viewproduct" src="~/Images/GetProductImage?productId=@(this.Model.ProductID)" alt="Product Image" style="padding: 8px;" />
}
</td>
<td>
@(string.IsNullOrEmpty(this.Model.SKU) ? this.Model.NonDownlandSKU : this.Model.SKU)
</td>
<td>@this.Model.ProductName</td>
<td>
@this.Model.Quantity
@Html.EditorFor(m => m.Quantity)
</td>
<td>
@string.Format("{0:C}", this.Model.PriceExVAT)
@Html.EditorFor(m => m.PriceExVAT)
</td>
<td>@string.Format("{0:C}", this.Model.VATTotal)</td>
<td>
@string.Format("{0:C}", this.Model.ItemTotal)
</td>
</tr>
查看代码:
@Html.EditorFor(m => m.PurchaseOrderItems);
只是另一个有趣的观点。在GET上,我根据数据库数据设置视图模型中的PurchaseOrder,然后设置PurchaseOrderItems。在Post上,我们似乎正在使用数据库中的数据再次设置视图模型中的purchaseOrder。根据传递给帖子的内容,视图模型中还正确设置了一些其他字段,但PurchaseOrderItems仍然为null。
您不应该在视图中进行此转换,因为以下表达式过于复杂,并且不受标准编辑器模板的支持:
m => m.PurchaseOrder.PurchaseOrderItems.ToList()[i].Quantity
因此,您显然应该使用一个真实的视图模型,在该模型中,您不只是将EF对象填充为属性,并用ViewModel
后缀命名(这就是这个PurchaseOrderViewModel
的样子)。因此,一旦你有了一个真实的视图模型,你就可以很容易地访问相应的属性,因为它的类型是IList<T>
:
@Html.EditorFor(m => m.PurchaseOrder.PurchaseOrderItems[i].Quantity);
话虽如此,如果出于某种原因,你继承了一些像这样的遗产垃圾,你仍然有一个变通办法。您可以使用编辑器模板。
因此,您首先在~/Shared/EditorTemplates/PurchaseOrderItem.cshtml
中添加以下模板:
@model PurchaseOrderItem
@Html.EditorFor(x => x.Quantity)
这个模板的名称非常重要,因为它都是按照约定工作的。它应该被命名为您拥有并位于~/Shared/EditorTemplates
中的ICollection<>
的类型。
然后简单地调整你的观点:
@Html.EditorFor(m => m.PurchaseOrder.PurchaseOrderItems);
在这种情况下,EditorFor
帮助程序将推断PurchaseOrderItems
是ICollection<T>
,它将自动循环遍历此集合的元素,并呈现您可以自定义的相应~/Shared/EditorTemplates/T.cshtml
模板。
更新:
看起来我需要发布一个简单的例子来说明如何使用编辑器模板。
一如既往,让我们从视图模型开始:
public class PurchaseOrderViewModel
{
public ICollection<PurchaseOrderItem> PurchaseOrderItems { get; set; }
}
public class PurchaseOrderItem
{
public int Quantity { get; set; }
}
然后是具有2个动作的控制器(一个用于显示表单,另一个用于处理来自该表单的提交数据):
public ActionResult Index()
{
var model = new PurchaseOrderViewModel();
// This information will probably come from querying some data store.
// That could be a SQL database for example. But for the purpose
// of this sample we are just hardcoding some values to illustrate
// the concept without any dependencies
model.PurchaseOrderItems = new[]
{
new PurchaseOrderItem
{
Quantity = 5,
}
};
return View(model);
}
[HttpPost]
public ActionResult Index(PurchaseOrderViewModel model)
{
// ... everything gets bound correctly here
}
然后是一个强类型视图:
@model PurchaseOrderViewModel
@using (Html.BeginForm())
{
@Html.EditorFor(x => x.PurchaseOrderItems)
<input type="submit" value="OK" />
}
最后是相应的编辑器模板(~/Shared/EditorTemapltes/PurchaseOrderItem.cshtml
):
@model PurchaseOrderItem
@Html.EditorFor(x => x.Quantity)