Più modelli in una vista

Voglio avere 2 modelli in un’unica vista. La pagina contiene sia LoginViewModel che RegisterViewModel .

per esempio

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

Devo creare un altro ViewModel che contenga questi 2 ViewModel?

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

Ho bisogno che gli attributi di convalida vengano portati in vista, ecco perché ho bisogno dei ViewModels.

Non c’è un altro modo come (senza il 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) } 

Ci sono molti modi …

  1. con il tuo BigViewModel che fai:

     @model BigViewModel @using(Html.BeginForm()) { @Html.EditorFor(o => o.LoginViewModel.Email) ... } 
  2. puoi creare 2 visualizzazioni aggiuntive

    Login.cshtml

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

    e register.cshtml stessa cosa

    dopo la creazione è necessario renderli nella vista principale e passarli viewmodel / viewdata

    quindi potrebbe essere così:

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

    o

     @{Html.RenderPartial("login", Model.LoginViewModel)} @{Html.RenderPartial("register", Model.RegisterViewModel)} 
  3. utilizzando le parti di ajax del tuo sito web diventa più indipendente

  4. iframes , ma probabilmente questo non è il caso

Consiglierei di usare Html.RenderAction e PartialViewResults per realizzare questo; ti consentirà di visualizzare gli stessi dati, ma ogni vista parziale avrà comunque un unico modello di visualizzazione e rimuoverà la necessità di un BigViewModel

Quindi la tua vista contiene qualcosa di simile al seguente:

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

Dove Login & Register sono entrambe le azioni nel controller definite come le seguenti:

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

L’ Login e il Register sarebbero quindi controlli utente che risiedono nella cartella View corrente o nella cartella condivisa e vorrebbero qualcosa del genere:

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

Ed ecco una singola azione del controller, visualizzare e visualizzare il file per ogni azione con ciascuno totalmente distinto e non dipendente l’uno dall’altro per nulla.

Un altro modo è usare:

 @model Tuple 

Ho spiegato come utilizzare questo metodo sia nella vista che nel controller per un altro esempio: Due modelli in una vista in ASP MVC 3

Nel tuo caso potresti implementarlo usando il seguente codice:

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

Si noti che ho modificato manualmente gli attributi Nome per ogni proprietà durante la creazione del modulo. Questo deve essere fatto, altrimenti non verrebbe mappato correttamente al parametro del modello tipo del metodo quando i valori vengono inviati al metodo associato per l’elaborazione. Suggerirei di utilizzare metodi separati per elaborare separatamente questi moduli, per questo esempio ho usato i metodi Login1 e Login2. Il metodo Login1 richiede di avere un parametro di tipo RegisterViewModel e Login2 richiede un parametro di tipo LoginViewModel.

se è necessario un link di azione, è ansible utilizzare:

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

nel metodo del controllore per la vista, una variabile di tipo Tuple deve essere creata e quindi passata alla vista.

Esempio:

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

oppure è ansible riempire le due istanze di LoginViewModel e RegisterViewModel con i valori e quindi passarlo alla vista.

Utilizza un modello di visualizzazione che contiene più modelli di visualizzazione:

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

Nella tua opinione:

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

Devo fare un’altra vista che contenga queste 2 viste?

Risposta: No

Non c’è un altro modo come (senza il BigViewModel):

, puoi usare Tupla (porta la magia in vista avendo più modelli).

Codice:

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

Aggiungi questo ModelCollection.cs ai tuoi modelli

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

controller:

 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

Voglio dire che la mia soluzione era come la risposta fornita su questa pagina di stackoverflow: ASP.NET MVC 4, più modelli in un’unica visualizzazione?

Tuttavia, nel mio caso, la query linq che hanno usato nel loro controller non ha funzionato per me.

Questa è la domanda:

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

Di conseguenza, “secondo te basta specificare che stai usando una collezione di modelli di visualizzazione” non ha funzionato neanche per me.

Tuttavia, una leggera variazione su quella soluzione ha funzionato per me. Ecco la mia soluzione nel caso in cui questo aiuti qualcuno.

Ecco il mio modello di vista in cui so che avrò una sola squadra ma quella squadra potrebbe avere più tabs (e ho una cartella ViewModels all’interno della mia cartella Models btw, da cui lo spazio dei nomi):

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

Ora questo è il mio controller. Questa è la differenza più significativa dalla soluzione nel collegamento di cui sopra. Costruisco il ViewModel per inviare alla vista in modo diverso.

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

Quindi, a mio avviso, non lo specificano come elenco. Faccio solo “@model TaskBoard.Models.ViewModels.TeamBoards” Quindi ho bisogno di un giro per ciascuno quando eseguo un’iterazione sulle tabs della squadra. Ecco la mia opinione:

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

Sono abbastanza nuovo per ASP.NET MVC quindi mi ci è voluto un po ‘per capirlo. Quindi, spero che questo post aiuti qualcuno a capirlo per il loro progetto in un lasso di tempo più breve. 🙂

  1. Crea una nuova class nel tuo modello e le proprietà di LoginViewModel e RegisterViewModel :

     public class UserDefinedModel() { property a1 as LoginViewModel property a2 as RegisterViewModel } 
  2. Quindi utilizzare UserDefinedModel nella visualizzazione.

puoi sempre passare il secondo object in un ViewBag o Visualizza dati.

un modo semplice per farlo

possiamo chiamare prima tutti i modelli

 @using project.Models 

quindi invia il tuo modello con viewbag

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

e in vista

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

quindi facilmente utilizzare questo come modello