Usuário com melhor resposta
MVC 5 - Criar uma view que tenha como fonte 2 models

Pergunta
-
Boa tarde,
Tenhos duas models com relacionamento 1:N. Cada model possui suas respectivas views, no entanto, existe a necessidade de uma terceira view que mostre dados das duas models.
Por exemplo: Model 1 > Nome, Tipo
Model 2 > Tipo, Código
Cada model tem seus respectivos controllers e views... View 1 mostra Nome e Tipo.... View 2 mostra Tipo e Código...
Minha dúvida é: Como faço para criar uma terceira view que mostre Nome, Tipo e Código?
Respostas
-
Voce tem que usar uma view_model
Na verdade o modelo mais indicado para trabalhar com MVC é no lugar do "Model" voce trabalhar com "View Model"
A view Model nao representa o modelo do banco de dados e sim o que voce quer exibir.. por exemplo, essa classe abaixo é model:
public class Employee : IEntity { public int Id { get; set; } // Employee's unique identifier public string FirstName { get; set; } // Employee's first name public string LastName { get; set; } // Employee's last name public DateTime DateCreated { get; set; } // Date when employee was created }
mas eu nao preciso nem do ID nem DateCreated para a construçao da minha view, entao eu crio uma viewmodel:
public class CreateEmployeeViewModel { public string FirstName { get; set; } public string LastName { get; set; } }
minha view é criada com a viewmodel:
@model MyProject.Web.ViewModels.CreateEmployeeViewModel <table> <tr> <td><b>First Name:</b></td> <td>@Html.TextBoxFor(x => x.FirstName, new { maxlength = "50", size = "50" }) @Html.ValidationMessageFor(x => x.FirstName) </td> </tr> <tr> <td><b>Last Name:</b></td> <td>@Html.TextBoxFor(x => x.LastName, new { maxlength = "50", size = "50" }) @Html.ValidationMessageFor(x => x.LastName) </td> </tr> </table>
e é no controler que é feito a transferencia:
public class EmployeeController : Controller { private readonly IEmployeeService employeeService; public EmployeeController(IEmployeeService employeeService) { this.employeeService = employeeService; } public ActionResult Create() { CreateEmployeeViewModel viewModel = new CreateEmployeeViewModel(); return View(viewModel); } public ActionResult Create(CreateEmployeeViewModel viewModel) { // Do what ever needs to be done before adding the employee to the database } }
ou seja, crie uma classe com Nome, Tipo e Codigo e depois crie um objeto com os valores corretos vindos do banco.
Isso tambem cria uma camada mais estavel e independente para view.
Veja o artigo abaixo:
http://eduardopires.net.br/2013/08/asp-net-mvc-view-model-pattern-quando-e-como-utilizar/
William John Adam Trindade
Analyste-programmeur
----------------------------------------------------------
- Sugerido como Resposta Aline Mansur quinta-feira, 27 de agosto de 2015 12:44
- Marcado como Resposta welington jrModerator quinta-feira, 14 de dezembro de 2017 17:30
-
PAra isso eu uso o automapper:
aqui alguns tutoriais:
http://elemarjr.net/2012/05/16/promovendo-automao-para-o-iisexpress-2/
http://www.akamud.com.br/2014/10/31/voce-conhece-o-automapper/
http://www.andrealveslima.com.br/blog/index.php/2015/05/06/para-que-serve-o-automapper/
http://eduardopires.net.br/2013/08/asp-net-mvc-utilizando-automapper-com-view-model-pattern/
William John Adam Trindade
Analyste-programmeur
----------------------------------------------------------
- Marcado como Resposta welington jrModerator quinta-feira, 14 de dezembro de 2017 17:30
Todas as Respostas
-
Voce tem que usar uma view_model
Na verdade o modelo mais indicado para trabalhar com MVC é no lugar do "Model" voce trabalhar com "View Model"
A view Model nao representa o modelo do banco de dados e sim o que voce quer exibir.. por exemplo, essa classe abaixo é model:
public class Employee : IEntity { public int Id { get; set; } // Employee's unique identifier public string FirstName { get; set; } // Employee's first name public string LastName { get; set; } // Employee's last name public DateTime DateCreated { get; set; } // Date when employee was created }
mas eu nao preciso nem do ID nem DateCreated para a construçao da minha view, entao eu crio uma viewmodel:
public class CreateEmployeeViewModel { public string FirstName { get; set; } public string LastName { get; set; } }
minha view é criada com a viewmodel:
@model MyProject.Web.ViewModels.CreateEmployeeViewModel <table> <tr> <td><b>First Name:</b></td> <td>@Html.TextBoxFor(x => x.FirstName, new { maxlength = "50", size = "50" }) @Html.ValidationMessageFor(x => x.FirstName) </td> </tr> <tr> <td><b>Last Name:</b></td> <td>@Html.TextBoxFor(x => x.LastName, new { maxlength = "50", size = "50" }) @Html.ValidationMessageFor(x => x.LastName) </td> </tr> </table>
e é no controler que é feito a transferencia:
public class EmployeeController : Controller { private readonly IEmployeeService employeeService; public EmployeeController(IEmployeeService employeeService) { this.employeeService = employeeService; } public ActionResult Create() { CreateEmployeeViewModel viewModel = new CreateEmployeeViewModel(); return View(viewModel); } public ActionResult Create(CreateEmployeeViewModel viewModel) { // Do what ever needs to be done before adding the employee to the database } }
ou seja, crie uma classe com Nome, Tipo e Codigo e depois crie um objeto com os valores corretos vindos do banco.
Isso tambem cria uma camada mais estavel e independente para view.
Veja o artigo abaixo:
http://eduardopires.net.br/2013/08/asp-net-mvc-view-model-pattern-quando-e-como-utilizar/
William John Adam Trindade
Analyste-programmeur
----------------------------------------------------------
- Sugerido como Resposta Aline Mansur quinta-feira, 27 de agosto de 2015 12:44
- Marcado como Resposta welington jrModerator quinta-feira, 14 de dezembro de 2017 17:30
-
Certo, compreendi a vantagem de utilizar a View Model.
No controller, é possível trazer do banco os valores através de uma query Linq e atribuir estes valores à instância da classe View Model?
Exemplo:
var query = from m in model1 select m
-
PAra isso eu uso o automapper:
aqui alguns tutoriais:
http://elemarjr.net/2012/05/16/promovendo-automao-para-o-iisexpress-2/
http://www.akamud.com.br/2014/10/31/voce-conhece-o-automapper/
http://www.andrealveslima.com.br/blog/index.php/2015/05/06/para-que-serve-o-automapper/
http://eduardopires.net.br/2013/08/asp-net-mvc-utilizando-automapper-com-view-model-pattern/
William John Adam Trindade
Analyste-programmeur
----------------------------------------------------------
- Marcado como Resposta welington jrModerator quinta-feira, 14 de dezembro de 2017 17:30
-
William, primeiramente muito obrigado pela ajuda.
Eu estava tentando seguir o exemplo do seu código, mas não consegui compreender a aplicação deste trecho:
public class EmployeeController : Controller { private readonly IEmployeeService employeeService; public EmployeeController(IEmployeeService employeeService) { this.employeeService = employeeService; }
Você poderia me ajudar novamente?
Criei a classe view model, mas ainda estou "apanhando" para realizar a transferência no controller.
Obrigado.
-
o codigo que eu postei é completamente hipotetico, basicamente sao dois objetos que possuem exatamente a mesma interface, o que na maioria das vezes é falso..
poste seu codigo do controler., desta forma nos poderemos te ajudar mais.
att
William John Adam Trindade
Analyste-programmeur
----------------------------------------------------------
-
Vamos lá, vou postar uma exemplo simplificado do que necessito:
Tenho duas Models com relacionamento 1:N
namespace TesteViewModel.Models { [Table("Pessoas")] public class Pessoa { [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public int PessoaID { get; set; } public string Nome { get; set; } [Key] public int Cpf { get; set; } public virtual ICollection<Veiculo> Veiculos { get; set; } } }
namespace TesteViewModel.Models { [Table("Veiculos")] public class Veiculo { [Key] [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public int VeiculoID { get; set; } public string Modelo { get; set; } public int CodigoProprietario { get; set; } [ForeignKey("CodigoProprietario")] public virtual Pessoa Pessoa { get; set; } }
Devido a necessidade de mostrar em uma view o resultado de uma consulta "join" entre as duas tabelas, criei uma ViewModel.
namespace TesteViewModel.ViewModels { public class JoinViewModel { [Key] public int CpfProprietario { get; set; } public string NomeProprietario { get; set; } public string ModeloVeiculo { get; set; } } }
Até aí tudo bem, o meu problema começa agora, pois ainda não compreendi como "dizer" à classe JoinViewModel que o campo CpfProprietário, corresponde ao campo Cpf da tabela Pessoas, NomeProprietário corresponde ao campo Nome da tabela pessoas e ModeloVeículo corresponde ao campo Modelo da tabela Veiculos.
Abaixo segue o código do Controller da ViewModel:
using System; using System.Collections.Generic; using System.Data; using System.Data.Entity; using System.Linq; using System.Net; using System.Web; using System.Web.Mvc; using TesteViewModel.Models; using TesteViewModel.ViewModels; namespace TesteViewModel.Controllers { public class JoinViewModelsController : Controller { private BancoContexto db = new BancoContexto(); // GET: JoinViewModels public ActionResult Index() { return View(db.JoinViewModels.ToList()); }
Mais uma vez agradeço pela ajuda!!
-
Faltou este trecho do código, onde executo a consulta linq:
public ActionResult Index() { var query = from p in db.Pessoas join v in db.Veiculos on p.Cpf equals v.CpfProprietario select new { cpfproprietario = p.Cpf, nomeproprietario = p.Nome, modeloveiculo = v.Modelo };
Daí em diante eu estou com dificuldade em transferir os dados da query para a instância da classe JoinViewModel
-
É só criar uma view model deste jeito:
public class Veiculo{ string cpfproprietario {get;set;} string nomeproprietario{get;set;} string modeloveiculo {get;set;} }
e no seu control:
public ActionResult Index() { var query = from p in db.Pessoas join v in db.Veiculos on p.Cpf equals v.CpfProprietario select new { cpfproprietario = p.Cpf, nomeproprietario = p.Nome, modeloveiculo = v.Modelo }; List<Veiculo> veiculos=new List<Veiculo>(); foreach(Object o in query){ Veiculo veiculo= new Veiculo();
veiculo.cpfproprietario=o.cpfproprietario;
veiculo.nomeproprietario=o.nomeproprietario;
veiculo.modeloveiculo=o.modeloveiculo; veiculos.add(veiculo); } return view(veiculos); }
É claro que com o automapper a soluçao seria mais elegante, mas deste jeito é mais legivel.
att
William John Adam Trindade
Analyste-programmeur
----------------------------------------------------------