2015-12-30 6 views
1

Я посмотрел this post, и, похоже, глава хочет сделать то же самое, на что я стремлюсь. Я унаследовал это приложение, и хотя я являюсь разработчиком .NET, материал MVC кажется волшебным по сравнению с другими структурами MVC на других языках, которые я предпочитаю. Мой код выступающий выглядят следующим образом:Пытается добавить ICollection в ViewModel в ASP.NET

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. 
    } 

В ТоварыЗаказе в модели является ICollection <> Я преобразование в IList для итеративного характера. Соответствующая часть обзора выглядит следующим образом:

Так почему же я не получаю данные OrderItems? Это связано с тем, что они скорее IList, чем ICollection? Если да, то каково обходное решение?

EDIT: Я изменил код представления, поскольку я что-то оставил, что пытался раньше.

EDIT 2: я принял во внимание текущие комментариев/ответов, так что теперь у меня есть следующие изменения сделаны:

ViewModel:

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/[email protected](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 в модели представления на основе данных базы данных. На почте появляется, что мы снова устанавливаем buyOrder в модели представления с данными из базы данных. Есть несколько других полей, которые корректно задаются в модели представления, основываясь на том, что передается на почту, но PurchaseOrderItems все равно null.

+2

Попробуйте использовать EditorTemplate. Это решит вашу проблему. Взгляните на этот пост http://stackoverflow.com/questions/25365043/mvc-create-object-and-related-objects-in-one-go/25365806#25365806 или http://stackoverflow.com/questions/ 34028606/update-relationship-on-edit-post-with-model-bind-from-mvc-controller/34029526 # 34029526 – Shyju

+0

Я обновил вопрос. Я попробовал EditorTemplate, но безрезультатно @Shyju –

ответ

1

Вы не должны делать это преобразование в представлении, поскольку следующее выражение просто слишком сложна и не поддерживается стандартными шаблонами редактора:

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) 

Имя этого шаблона очень важно, потому что все работы по соглашению. Его следует назвать типом ICollection<>, который у вас есть и находится в ~/Shared/EditorTemplates.

А потом просто адаптировать свой вид так:

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

EditorFor помощник в этом случае будет сделать вывод, что PurchaseOrderItems является ICollection<T>, и он будет автоматически перебрать элементы этой коллекции и сделать соответствующий ~/Shared/EditorTemplates/T.cshtml шаблон которые вы можете настроить.


UPDATE:

Похоже, мне нужно, чтобы добавить простой пример, чтобы проиллюстрировать, как можно использовать шаблоны редактора.

Как всегда давайте начнем с моделью представления (ы):

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) 
+0

Извините за вводящий в заблуждение код. Я изменил его сейчас на что-то другое, что не работает, что больше похоже на код, который мне бы хотелось в итоге. –

+1

Вы изменили свой вопрос, но, к сожалению, в этом вопросе вы показали некоторую модель, которая называется 'PurchaseOrderViewModel', которая не имеет никакого свойства коллекции. Тем не менее, по-вашему, вы, похоже, используете некоторый '@ Html.EditorFor (m => m.OrderItems [i] .Quantity);' call, но я не вижу нигде в вашей модели представления свойство 'OrderItems'. Но во всех случаях вы должны следовать моим советам и использовать шаблоны редактора. Просто определите шаблон редактора для класса 'OrderItem', и тогда вам даже не нужно писать цикл' for' в вашем представлении, но '@ Html.EditorFor (x => x.OrderItems)'. –

+0

обновлен. Извините, я стараюсь не перегружать ненужным кодом, но я должен по-настоящему дважды проверить вещи, которые я выпускаю. Извинения –

Смежные вопросы