asp.net-mvc - vista - mvc submit button action




Múltiples modelos en una vista. (7)

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

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

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


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

Otra forma es usar:

@model Tuple<LoginViewModel,RegisterViewModel>

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 su caso podría implementarlo utilizando el siguiente código:

En la vista:

@using YourProjectNamespace.Models;
@model Tuple<LoginViewModel,RegisterViewModel>

@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 crear el formulario. Esto debe hacerse; de ​​lo contrario, no se asignaría correctamente al parámetro del tipo de modelo del método cuando los valores se envían al método asociado para su procesamiento. Yo sugeriría usar métodos separados para procesar estos formularios por separado, para este ejemplo usé los métodos Login1 e 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 enlace de acción, puede usar:

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

en el método del controlador para la vista, se debe crear una variable de tipo Tuple y luego pasarla a la vista.

Ejemplo:

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

o puede llenar los dos casos de LoginViewModel y RegisterViewModel con valores y luego pasarlos a la vista.


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.


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)

una manera simple de hacer eso

Podemos llamar a todos los modelos primero

@using project.Models

luego envía tu 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<YourModel> Name = (List<YourModel>)ViewBag.Name ;

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

entonces utiliza fácilmente este modelo como