2017-02-11 29 views
2

Я новичок в MVC5 и просто пытаюсь понять использование ViewModels. Мои вопросы: если мне нужно создать экземпляр класса модели в контроллере моей модели ViewModel. Я создаю базу данных для организации счетов и имею модель Cash, которая сопоставляется с таблицей базы данных, и CashViewModel для просмотра/редактирования данных.Нужно ли создавать экземпляр класса Model в ViewModel в MVC5?

Вот моя модель:

public class Cash 
{ 
    public int CashId { get; set; } 
    public decimal CashAmount { get; set; } 
    public int CashTypeId { get; set; } 
    public DateTime DateModified { get; set; } 
    public CashType CashType { get; set; } 
} 

Вот мой ViewModel:

public class CashViewModel 
{ 
    public int CashId { get; set; } 
    public decimal CashAmount { get; set; } 
    public int CashTypeId { get; set; } 
    public SelectList CashTypeSelectList { get; set; } 
} 

Вот мой контроллер:

public ActionResult Create([Bind(Include = "CashAmount,CashTypeId")] CashViewModel cashVM) 
    { 
     if (ModelState.IsValid) 
     { 
      var cash = db.Cashes.Create(); 
      cash.DateModified = DateTime.Now; 
      cash.CashAmount = cashVM.CashAmount; 
      cash.CashTypeId = cashVM.CashTypeId; 
      db.Cashes.Add(cash); 
      db.SaveChanges(); 
      return RedirectToAction("Index"); 
     } 

     ViewBag.CashTypeId = new SelectList(db.CashTypes, "CashTypeId", "CashTypeName", cashVM.CashTypeId); 
     return View(cashVM); 
    } 

Я создаю экземпляр модели Наличный и сопоставление моего класса ViewModel с моим классом модели. Это верно? Когда я начинаю делать проекты, в которых есть несколько моделей с несколькими атрибутами в одной ViewModel, кажется, что он быстро выйдет из-под контроля.

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

+0

Что вы делаете правильно. См. [Что такое ViewModel в MVC?] (Http://stackoverflow.com/questions/11064316/what-is-viewmodel-in-mvc). Однако удалите свой 'ViewBag.CashTypeId = новый SelectList (....)' и замените его на 'cashVM.CashType = new SelectList (db.CashTypes," CashTypeId "," CashTypeName ");' (обратите внимание на 4-й параметр) - в представлении должно быть '@ Html.DropDownListFor (m => m.CashTypeId, Model.CashType, ...)' –

ответ

2

ViewModels - это в основном обеспечение DTO между View и Controller, что похоже на то, что вы делаете. Однако ваша модель выглядит неправильно, поскольку у вас должен быть только CashType, а не CashTypeId, поскольку модель CashType имеет идентификатор Id и Cash. Проблема с наличием обоих заключается в том, что они не синхронизируются, и я даже не помню, какой EF выбирает как авторитетный.

Кроме того, похоже, что вы это поняли. В вашей модели ViewModel есть SelectList со значениями для вашего представления для рендеринга и CashTypeId для вашего клиента, чтобы присвоить значение. Без CashTypeId в вашей основной сущности вам нужно будет создать новый объект CashType и присвоить ему соответствующий идентификатор (если это Entity Framework).

Один последний совет: не выполняйте эти операции с БД в своем контроллере. Проверьте repository pattern и, возможно, даже разместите бизнес-слой между ними.

+0

Спасибо за ваш ответ. Я читал книгу Wrox Professional ASP.NET MVC 5, просматривая пример MVC Music Store, и они использовали идентификаторы внешнего ключа для создания отношений внешнего ключа в базе данных. Я просто протестировал то, что вы сказали с некоторыми тестовыми классами, и ссылаясь на одну модель в другой настройке, связанную с внешним ключом ... TIL. Чтобы следить за репозиторием, у них есть базовые функции CRUD, но мне нужно будет сопоставить данные моего представления с моделями для всех моделей, чтобы сделать обновления для нормализованных таблиц? – Andy

+0

Ваш репозиторий должен иметь дело только с моделями/сущностями. ViewModels не должны существовать вне вашего проекта ASP.NET MVC. Итак, да, вам нужно будет сопоставить ViewModel с Model. Существует пакет под названием AutoMapper, который может помочь в этом, хотя я лично его не использовал. –

1

Я создаю экземпляр модели Cash и сопоставляю свой класс ViewModel с классом модели. Это верно? Когда я начинаю делать проекты, в которых есть несколько моделей с несколькими атрибутами в одной ViewModel, кажется, что он быстро выйдет из-под контроля.

Нет ничего плохого в том, что вы делаете. Тем не менее, для сопоставления модели вашего домена с моделью для представления (модель представления) вы можете использовать библиотеку для отображения для вас. Я использую AutoMapper. Представьте, у вас есть это:

public class Cash { 
    public string Prop1 { get; set; } 
} 

public class CashViewModel { 
    public string Prop1 { get; set; } 
} 

В вашем методе запуска Application_Start(), вы можете поручить AutoMapper как карту из вашей доменной модели к модели для представления, как это:

protected void Application_Start() 
{ 
    // ReverseMap will do vice-versa mapping 
    // If property names are the same, then AutoMapper will take care of it 
    // for you. 
    Mapper.Initialize(x => x.CreateMap<Cash, CashViewModel>().ReverseMap()); 

    // Of course you will have many cases where the property names 
    // are different 
    // For that case you will need to do this 
    // Imagine your model has a property called Name and view model has 
    // FirstName 
    Mapper.CreateMap<CashViewModel, Cash>() 
      .ForMember(model => model.Name, map => map.MapFrom(vm => vm.FirstName)); 
} 

Тогда в контроллере вы просто сделать это, чтобы преобразовать из модели представления в модели предметной области:

var model = Mapper.Map<Cash>(cashViewModel); 

красота этого подхода заключается в том, что все ваше отображение будет в одном месте.В заключение, here - отличная статья, которая охватывает большую часть того, что вы ищете, и многое другое.