MVC e Entity Framework Html.DisplayNameFor com Composite ViewModel
Estou bastante confortável com o MVVM usando o WPF / Silverlight, mas esta é a minha primeira tentativa em um aplicativo da web do MVC ... apenas um exemplo do meu histórico.
Eu criei um controlador chamado TestSitesController que foi gerado automaticamente a partir da classe de modelo "Site" no meu Entity Framework Model (o modelo que gera as ações e visualizações de leitura / gravação). A única coisa que eu modifiquei foi em 3 pontos, havia um parâmetro padrão de Guid id = null para alguns métodos. Acabei de me livrar do "= null" tudo funciona bem. Aqui está um exemplo do que eu mudei
public ActionResult Delete(Guid id = null)
{
//....
}
Isso foi mudado para
public ActionResult Delete(Guid id)
{
//....
}
O modelo do site não é nada especial SiteId, Abreviação e DisplayName ... tentando mantê-lo o mais simples possível para esta questão. Ok, então eu corro o site e vou para o htpp: //.../TestSites/ e tudo funciona perfeitamente.
Percebi que todas as minhas visualizações (Create, Delete, Details e Edit) estão usando um @model MVCWeb.MyEntities.Site, com o qual eu estou perfeitamente bem por enquanto; mas na visão Index.cshtml notei que estava usando um
@model IEnumerable<MVCWeb.MyEntities.Site>
Isso funciona bem para o modelo gerado, mas eu gostaria de usar um "Modelo de exibição composta" e talvez seja aqui que eu estou tentando misturar meus conhecimentos de MVVM, mas farei isso se for possível. Na minha opinião, um Modelo de Visualização Composta é apenas um Modelo específico para uma exibição composta de 1 ou mais Modelos de Entidade, juntamente com propriedades adicionais, como SelectedSiteId, etc.
Então eu criei um ViewModel muito simples chamado TestSitesViewModel
public class TestSitesViewModel
{
//Eventually this will be added to a base ViewModel to get rid
//of the ViewBag dependencies
[Display(Name = "Web Page Title")]
public string WebPageTitle;
public IEnumerable<MVCWeb.MyEntities.Site> Sites;
//Other Entities, IEnumberables, or properties go here
//Not important for this example
}
Então no meu controlador eu adicionei um método de ação chamado IndexWithViewModel
public ActionResult IndexWithViewModel()
{
var vm = new TestSitesViewModel();
vm.WebPageTitle = "Sites With Composite View Model";
vm.Sites = db.Sites.ToList();
return View(vm);
}
Em seguida, fiz uma cópia do Index.cshtml e nomeei IndexWithModel.cshtml para corresponder ao meu novo nome do método ActionResult. Eu mudei a linha superior de
@model IEnumerable<MVCWeb.MyEntities.Site>
Para
@model MVCWeb.Models.TestSitesViewModel
Eu adicionei isso antes da seção da tabela para testar o DisplayNameFor e o DisplayFor
@Html.DisplayNameFor(model => model.WebPageTitle)
@Html.DisplayFor(model => model.WebPageTitle)
<br />
Mudou o
@foreach (var item in Model) {
Para
@foreach (var item in Model.Sites) {
E comentou a seção tr que contém todos os cabeçalhos da tabela por enquanto. Tudo funciona perfeitamente, exceto que o @ Html.DisplayNameFor está exibindo o nome da variável "WebPageTitle" em vez de usar "Web Page Title" como indicado no atributo Display da Anotação de Dados em
[Display(Name = "Web Page Title")]
public string WebPageTitle;
Além disso, se eu comentar novamente na seção tr que contém as informações do cabeçalho da tabela. Eu não posso para a vida de mim descobrir o que colocar em Eu tentei model.Sites.Abbreviation, model.Sites [0] .Abbreviation, e várias outras combinações, mas recebo erros.
<tr>
<th>
@Html.DisplayNameFor(model => model.Abbreviation)
</th>
<th>
@Html.DisplayNameFor(model => model.DisplayName)
</th>
<th></th>
</tr>
Então, o que devo usar lá? Eu não tenho certeza porque model.Sites.Abbreviation não funciona como Sites é exatamente o mesmo tipo que foi usado como modelo no Index.cshtml original