asp.net-mvc multiples - Múltiples modelos en una vista.




models in (9)

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

¿Necesito 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 remitan a la vista, por eso necesito los ViewModels.

¿No hay otra forma 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)
 }

Answers

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 único y eliminará la necesidad de un BigViewModel

Así que tu vista contiene algo como lo siguiente:

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

Donde Login y Register son acciones en su controlador definidas como las siguientes:

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

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

El Login y el Register serían los controles de usuario que residen en la carpeta de vista actual o en la carpeta compartida y les gustaría 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 ahí tienes un único controlador de acción, ver y ver el archivo para cada acción con cada uno totalmente distinto y no dependen uno del otro para nada.


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


Use un modelo de vista que contenga múltiples 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)

¿Necesito hacer otra vista que contenga estas 2 vistas?

Respuesta: No

¿No hay otra forma como (sin BigViewModel):

, puedes usar Tuple (trae magia a la vista con varios modelos).

Código:

 @model Tuple<LoginViewModel, RegisterViewModel>


    @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)
     }

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

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


Agregue este ModelCollection.cs a sus modelos

using System;
using System.Collections.Generic;

namespace ModelContainer
{
  public class ModelCollection
  {
   private Dictionary<Type, object> models = new Dictionary<Type, object>();

   public void AddModel<T>(T t)
   {
      models.Add(t.GetType(), t);
   }

   public T GetModel<T>()
   {
     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<Model1>()).Name);
}

<h2>Model2: @((Model.GetModel<Model2>()).Number</h2>

@((Model.GetModel<Model3>()).SomeProperty

Hay muchas maneras ...

  1. Con su BigViewModel usted 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, debe presentarlos en la vista principal y pasarles el modelo de vista / datos de visualización

    por lo que 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. El uso de partes de ajax de su sitio web se vuelve más independiente.

  4. iframes , pero probablemente este no sea el caso


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

Sin embargo, en mi caso, la consulta de linq que usaron 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, simplemente especifique que está utilizando una colección de modelos de vista" tampoco me funcionó.

Sin embargo, una ligera 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 solo tendré un equipo, pero ese equipo puede tener varias placas (y tengo una carpeta ViewModels dentro de mi carpeta de Modelos por cierto, por lo tanto, el espacio de nombres):

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

Ahora este es mi controlador. Esta es la diferencia más significativa de la solución en el enlace mencionado anteriormente. Construyo el 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. Simplemente hago "@model TaskBoard.Models.ViewModels.TeamBoards" Luego solo necesito una para cada una cuando itero sobre los tableros del equipo. Esta es mi opinión:

@model TaskBoard.Models.ViewModels.TeamBoards

@{
    ViewBag.Title = "Details";
}

<h2>Details</h2>

<div>
    <h4>Team</h4>
    <hr />


    @Html.ActionLink("Create New Board", "Create", "Board", new { TeamId = @Model.Team.TeamId}, null)
    <dl class="dl-horizontal">
        <dt>
            @Html.DisplayNameFor(model => Model.Team.Name)
        </dt>

        <dd>
            @Html.DisplayFor(model => Model.Team.Name)
            <ul>
                @foreach(var board in Model.Boards)
                { 
                    <li>@Html.DisplayFor(model => board.BoardName)</li>
                }
            </ul>
        </dd>

    </dl>
</div>
<p>
    @Html.ActionLink("Edit", "Edit", new { id = Model.Team.TeamId }) |
    @Html.ActionLink("Back to List", "Index")
</p>

Soy bastante nuevo en ASP.NET MVC, por lo que me tomó un poco de tiempo resolverlo. Por lo tanto, espero que esta publicación ayude a alguien a descifrarlo para su proyecto en un plazo más breve. :-)


Si usa [Mostrar (Nombre = "")] para las propiedades de su modelo, esto causará el error que recibe. Para resolver este problema, debe evitar utilizar el atributo de nombre de visualización vacío.

[Display(Name = "")] //this line is the cause of error
public string PromotionCode { get; set; }






asp.net-mvc asp.net-mvc-3