简体   繁体   English

尝试将ICollection添加到ASP.NET中的ViewModel

[英]Trying to add a ICollection to a ViewModel in ASP.NET

I have had a look at this post and the chap there seems to want to do the same thing that I am aiming for. 我看了这篇文章 ,那里的小伙子似乎想做我要达到的目标。 I have inherited this application and although I am a .NET developer the MVC stuff seems magical in comparison to other MVC frameworks in other languages which I prefer. 我继承了此应用程序,尽管我是.NET开发人员,但与我喜欢的其他语言的其他MVC框架相比,MVC的东西似乎很神奇。 My salient code is as follows: 我的主要代码如下:

public class PurchaseOrderViewModel
{
    public PurchaseOrderViewModel()
    {
        this.PurchaseOrder = new PurchaseOrder();
    }
    // Some other fields here....
    public PurchaseOrder PurchaseOrder { get; set; }

    public IList<PurchaseOrderItem> OrderItems { get; set; }
 }

The controller: 控制器:

    [HttpPost]
    public ActionResult Details(PurchaseOrderViewModel viewModel)
    {
       // bunch of stuff. the viewModels.OrderItems here is null. 
    }

The OrderItems in the model is a ICollection<> I am converting to an IList for the iterative nature. 模型中的OrderItems是一个ICollection <>,出于迭代的性质,我正在将其转换为IList。 The relevant part of the view is as follows: 该视图的相关部分如下:

 @model PurchaseOrderViewModel
 @for (var i = 0; i < this.Model.OrderItems.Count; i++)
 {                
    @Html.EditorFor(m => m.OrderItems[i].Quantity);
 }

So why am I not getting the OrderItems coming through? 那我为什么不让OrderItems通过呢? Is this to do with the fact that they are IList rather than ICollection? 这与它们是IList而不是ICollection有关吗? If so, what is the workaround? 如果是这样,解决方法是什么?

EDIT: I have changed the view code as I left something in that I was trying before. 编辑:我更改了视图代码,因为我在尝试之前留下了一些东西。

EDIT 2: I took into consideration current comment/answers so now I have the following changes made: 编辑2:我考虑了当前的评论/答案,所以现在我做了以下更改:

viewModel: 视图模型:

    public ICollection<PurchaseOrderItem> PurchaseOrderItems { get; set; }

PurchaseOrderItem.cshtml: (I have left this actually as it is in code just in case): 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>

View code: 查看代码:

@Html.EditorFor(m => m.PurchaseOrderItems);

Just another interesting point. 只是另一个有趣的观点。 On the GET I set the PurchaseOrder and then the PurchaseOrderItems in the view model based on the database data. 在GET上,根据数据库数据在视图模型中设置PurchaseOrder,然后设置PurchaseOrderItems。 On the Post it appears that we are setting the purchaseOrder in the view model with data from the database again. 在“发布”上,似乎我们再次使用来自数据库的数据在视图模型中设置了purchaseOrder。 There are some other fields that are being set correctly in the view model based on what is passed to the post but the PurchaseOrderItems is still null. 根据传递到帖子的内容,在视图模型中还可以正确设置其他一些字段,但是PurchaseOrderItems仍然为null。

You should not be doing this conversion in the view because the following expression simply is too complex and not supported by the standard editor templates: 您不应该在视图中进行此转换,因为以下表达式太复杂了,标准编辑器模板不支持以下表达式:

m => m.PurchaseOrder.PurchaseOrderItems.ToList()[i].Quantity

So, you should obviously use a real view model in which you don't just stuff your EF objects as properties and naming it with the ViewModel suffix (which is what this PurchaseOrderViewModel look like). 因此,您显然应该使用一个真实的视图模型,在该模型中,您不仅要将EF对象作为属性填充,并用ViewModel后缀(这就是PurchaseOrderViewModel样子)进行命名。 So once you have a real view model you can easily access the corresponding property because it will be of type IList<T> : 因此,一旦有了真实的视图模型,就可以轻松访问相应的属性,因为它将是IList<T>类型:

@Html.EditorFor(m => m.PurchaseOrder.PurchaseOrderItems[i].Quantity);

This being said, if for some reason you have inherited some legacy crap like that there's still a workaround for you. 话虽这么说,但是如果您出于某种原因继承了一些旧的废话,那么仍然有解决方法。 You can use editor templates. 您可以使用编辑器模板。

So you start by adding the following template in ~/Shared/EditorTemplates/PurchaseOrderItem.cshtml : 因此,您首先需要在~/Shared/EditorTemplates/PurchaseOrderItem.cshtml添加以下模板:

@model PurchaseOrderItem
@Html.EditorFor(x => x.Quantity)

The name of this template is very important because it all works by convention. 该模板的名称非常重要,因为所有模板均按惯例工作。 It should be named as the type of the ICollection<> that you have and located in ~/Shared/EditorTemplates . 应该将其命名为您拥有的ICollection<>的类型,该类型位于~/Shared/EditorTemplates

And then simply adapt your view like that: 然后像这样简单地调整您的视图:

@Html.EditorFor(m => m.PurchaseOrder.PurchaseOrderItems);

The EditorFor helper in this case will infer that PurchaseOrderItems is an ICollection<T> and it will automatically loop through the elements of this collection and render the corresponding ~/Shared/EditorTemplates/T.cshtml template that you could customize. 在这种情况下, EditorFor帮助程序将推断PurchaseOrderItemsICollection<T> ,它将自动循环浏览此集合的元素并呈现您可以自定义的对应~/Shared/EditorTemplates/T.cshtml模板。


UPDATE: 更新:

It looks like I need to post a simple example to illustrate how editor templates can be used. 看来我需要发布一个简单的示例来说明如何使用编辑器模板。

As always let's start with the view model(s): 与往常一样,让我们​​从视图模型开始:

public class PurchaseOrderViewModel
{
    public ICollection<PurchaseOrderItem> PurchaseOrderItems { get; set; }
}

public class PurchaseOrderItem
{
    public int Quantity { get; set; }
}

then a controller with 2 actions (one for displaying a form and one for handling the submitted data from this form): 然后是一个控制器,执行以下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
}

then a strongly typed view: 然后是强类型视图:

@model PurchaseOrderViewModel
@using (Html.BeginForm())
{
    @Html.EditorFor(x => x.PurchaseOrderItems)
    <input type="submit" value="OK" />
}

and finally the corresponding editor template ( ~/Shared/EditorTemapltes/PurchaseOrderItem.cshtml ): 最后是相应的编辑器模板( ~/Shared/EditorTemapltes/PurchaseOrderItem.cshtml ):

@model PurchaseOrderItem
@Html.EditorFor(x => x.Quantity)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM