Múltiples modelos en una vista

Quiero tener 2 modelos en una vista. La página contiene LoginViewModel y RegisterViewModel .

p.ej

 public class LoginViewModel { public string Email { get; set; } public string Password { get; set; } } public class RegisterViewModel { public string Name { get; set; } public string Email { get; set; } public string Password { get; set; } } 

¿Debo hacer otro ViewModel que contenga estos 2 ViewModels?

 public BigViewModel { public LoginViewModel LoginViewModel{get; set;} public RegisterViewModel RegisterViewModel {get; set;} } 

Necesito que los atributos de validación se envíen a la vista, esta es la razón por la que necesito ViewModels.

¿No hay otra manera como (sin BigViewModel )?

  @model ViewModel.RegisterViewModel @using (Html.BeginForm("Login", "Auth", FormMethod.Post)) { @Html.TextBoxFor(model => model.Name) @Html.TextBoxFor(model => model.Email) @Html.PasswordFor(model => model.Password) } @model ViewModel.LoginViewModel @using (Html.BeginForm("Login", "Auth", FormMethod.Post)) { @Html.TextBoxFor(model => model.Email) @Html.PasswordFor(model => model.Password) } 

Hay muchas formas …

  1. con su BigViewModel lo hace:

     @model BigViewModel @using(Html.BeginForm()) { @Html.EditorFor(o => o.LoginViewModel.Email) ... } 
  2. puedes crear 2 vistas adicionales

    Login.cshtml

     @model ViewModel.LoginViewModel @using (Html.BeginForm("Login", "Auth", FormMethod.Post)) { @Html.TextBoxFor(model => model.Email) @Html.PasswordFor(model => model.Password) } 

    y register.cshtml lo mismo

    después de la creación, debes renderizarlos en la vista principal y pasarlos al viewmodel / viewdata

    entonces podría ser así:

     @{Html.RenderPartial("login", ViewBag.Login);} @{Html.RenderPartial("register", ViewBag.Register);} 

    o

     @{Html.RenderPartial("login", Model.LoginViewModel)} @{Html.RenderPartial("register", Model.RegisterViewModel)} 
  3. usando ajax partes de su sitio web se vuelven más independientes

  4. iframes , pero probablemente este no es el caso

Recomiendo usar Html.RenderAction y PartialViewResults para lograr esto; le permitirá mostrar los mismos datos, pero cada vista parcial aún tendrá un modelo de vista única y elimina la necesidad de un BigViewModel

Entonces su vista contiene algo como lo siguiente:

 @Html.RenderAction("Login") @Html.RenderAction("Register") 

Donde Login y Register son ambas acciones en su controlador definidas de la siguiente manera:

 public PartialViewResult Login( ) { return PartialView( "Login", new LoginViewModel() ); } public PartialViewResult Register( ) { return PartialView( "Register", new RegisterViewModel() ); } 

El Login y el Register serían entonces controles de usuario que residen en la carpeta Ver actual o en la carpeta Compartidos y desearían algo como esto:

/Views/Shared/Login.cshtml: (o /Views/MyView/Login.cshtml)

 @model LoginViewModel @using (Html.BeginForm("Login", "Auth", FormMethod.Post)) { @Html.TextBoxFor(model => model.Email) @Html.PasswordFor(model => model.Password) } 

/Views/Shared/Register.cshtml: (o /Views/MyView/Register.cshtml)

 @model ViewModel.RegisterViewModel @using (Html.BeginForm("Login", "Auth", FormMethod.Post)) { @Html.TextBoxFor(model => model.Name) @Html.TextBoxFor(model => model.Email) @Html.PasswordFor(model => model.Password) } 

Y allí tienes una sola acción de controlador, ver y ver el archivo de cada acción, cada una de ellas es totalmente distinta y no depende de ningún otro para nada.

Otra forma es usar:

 @model Tuple 

He explicado cómo usar este método tanto en la vista como en el controlador para otro ejemplo: dos modelos en una vista en ASP MVC 3

En tu caso, puedes implementarlo usando el siguiente código:

En la vista:

 @using YourProjectNamespace.Models; @model Tuple @using (Html.BeginForm("Login1", "Auth", FormMethod.Post)) { @Html.TextBoxFor(tuple => tuple.Item2.Name, new {@Name="Name"}) @Html.TextBoxFor(tuple => tuple.Item2.Email, new {@Name="Email"}) @Html.PasswordFor(tuple => tuple.Item2.Password, new {@Name="Password"}) } @using (Html.BeginForm("Login2", "Auth", FormMethod.Post)) { @Html.TextBoxFor(tuple => tuple.Item1.Email, new {@Name="Email"}) @Html.PasswordFor(tuple => tuple.Item1.Password, new {@Name="Password"}) } 

Tenga en cuenta que he cambiado manualmente los atributos de Nombre para cada propiedad al comstackr el formulario. Esto debe hacerse, de lo contrario no se correlacionaría adecuadamente con el parámetro del modelo de tipo de modelo cuando los valores se envían al método asociado para su procesamiento. Sugeriría usar métodos separados para procesar estos formularios por separado, para este ejemplo usé los métodos de Login1 y Login2. El método Login1 requiere tener un parámetro de tipo RegisterViewModel y Login2 requiere un parámetro de tipo LoginViewModel.

si se requiere un actionlink, puede usar:

 @Html.ActionLink("Edit", "Edit", new { id=Model.Item1.Id }) 

en el método del controlador para la vista, una variable de tipo Tuple necesita ser creada y luego pasada a la vista.

Ejemplo:

 public ActionResult Details() { var tuple = new Tuple(new LoginViewModel(),new RegisterViewModel()); return View(tuple); } 

o puede completar las dos instancias de LoginViewModel y RegisterViewModel con valores y luego pasarlo a la vista.

Use un modelo de vista que contenga varios modelos de vista:

  namespace MyProject.Web.ViewModels { public class UserViewModel { public UserDto User { get; set; } public ProductDto Product { get; set; } public AddressDto Address { get; set; } } } 

En su opinión:

  @model MyProject.Web.ViewModels.UserViewModel @Html.LabelFor(model => model.User.UserName) @Html.LabelFor(model => model.Product.ProductName) @Html.LabelFor(model => model.Address.StreetName) 

¿Debo hacer otra vista que contenga estas 2 vistas?

Respuesta: no

¿No hay otra manera como (sin BigViewModel)?

, puedes usar Tuple (trae magia a la vista con múltiples modelos).

Código:

  @model Tuple @using (Html.BeginForm("Login", "Auth", FormMethod.Post)) { @Html.TextBoxFor(tuple=> tuple.Item.Name) @Html.TextBoxFor(tuple=> tuple.Item.Email) @Html.PasswordFor(tuple=> tuple.Item.Password) } @using (Html.BeginForm("Login", "Auth", FormMethod.Post)) { @Html.TextBoxFor(tuple=> tuple.Item1.Email) @Html.PasswordFor(tuple=> tuple.Item1.Password) } 

Agregue este ModelCollection.cs a sus Modelos

 using System; using System.Collections.Generic; namespace ModelContainer { public class ModelCollection { private Dictionary models = new Dictionary(); public void AddModel(T t) { models.Add(t.GetType(), t); } public T GetModel() { return (T)models[typeof(T)]; } } } 

Controlador:

 public class SampleController : Controller { public ActionResult Index() { var model1 = new Model1(); var model2 = new Model2(); var model3 = new Model3(); // Do something var modelCollection = new ModelCollection(); modelCollection.AddModel(model1); modelCollection.AddModel(model2); modelCollection.AddModel(model3); return View(modelCollection); } } 

La vista:

 enter code here @using Models @model ModelCollection @{ ViewBag.Title = "Model1: " + ((Model.GetModel()).Name); } 

Model2: @((Model.GetModel()).Number

@((Model.GetModel()).SomeProperty

Quiero decir que mi solución fue como la respuesta proporcionada en esta página stackoverflow: ASP.NET MVC 4, ¿varios modelos en una vista?

Sin embargo, en mi caso, la consulta de linq que utilizaron en su controlador no funcionó para mí.

Esta es dicha consulta:

 var viewModels = (from e in db.Engineers select new MyViewModel { Engineer = e, Elements = e.Elements, }) .ToList(); 

En consecuencia, “en su opinión solo especifique que está utilizando una colección de modelos de vista” tampoco funcionó para mí.

Sin embargo, una pequeña variación en esa solución funcionó para mí. Aquí está mi solución en caso de que esto ayude a alguien.

Aquí está mi modelo de vista en el que sé que tendré solo un equipo, pero ese equipo puede tener varias placas (y tengo una carpeta ViewModels dentro de mi carpeta de Modelos por cierto, de ahí el espacio de nombres):

 namespace TaskBoard.Models.ViewModels { public class TeamBoards { public Team Team { get; set; } public List Boards { get; set; } } } 

Ahora este es mi controlador. Esta es la diferencia más significativa de la solución en el enlace al que se hace referencia anteriormente. Construyo ViewModel para enviar a la vista de manera diferente.

 public ActionResult Details(int? id) { if (id == null) { return new HttpStatusCodeResult(HttpStatusCode.BadRequest); } TeamBoards teamBoards = new TeamBoards(); teamBoards.Boards = (from b in db.Boards where b.TeamId == id select b).ToList(); teamBoards.Team = (from t in db.Teams where t.TeamId == id select t).FirstOrDefault(); if (teamBoards == null) { return HttpNotFound(); } return View(teamBoards); } 

Entonces, en mi opinión, no lo especifico como una lista. Acabo de hacer “@model TaskBoard.Models.ViewModels.TeamBoards” Entonces solo necesito una para cada uno cuando itero sobre los tableros del equipo. Aquí está mi vista:

 @model TaskBoard.Models.ViewModels.TeamBoards @{ ViewBag.Title = "Details"; } 

Details

Team


@Html.ActionLink("Create New Board", "Create", "Board", new { TeamId = @Model.Team.TeamId}, null)
@Html.DisplayNameFor(model => Model.Team.Name)
@Html.DisplayFor(model => Model.Team.Name)
    @foreach(var board in Model.Boards) {
  • @Html.DisplayFor(model => board.BoardName)
  • }

@Html.ActionLink("Edit", "Edit", new { id = Model.Team.TeamId }) | @Html.ActionLink("Back to List", "Index")

Soy bastante nuevo en ASP.NET MVC, así que me tomó un poco de tiempo resolver esto. Por lo tanto, espero que esta publicación ayude a alguien a resolver su proyecto en un plazo de tiempo más corto. 🙂

  1. Cree una nueva clase en su modelo y propiedades de LoginViewModel y RegisterViewModel :

     public class UserDefinedModel() { property a1 as LoginViewModel property a2 as RegisterViewModel } 
  2. Luego use UserDefinedModel en su vista.

siempre puede pasar el segundo objeto en un ViewBag o Ver datos.

una forma simple de hacer eso

podemos llamar primero a todos los modelos

 @using project.Models 

a continuación, envíe su modelo con viewbag

 // for list ViewBag.Name = db.YourModel.ToList(); // for one ViewBag.Name = db.YourModel.Find(id); 

y a la vista

 // for list List Name = (List)ViewBag.Name ; //for one YourModel Name = (YourModel)ViewBag.Name ; 

entonces fácilmente use esto como Modelo