Plusieurs modèles en vue
je veux avoir 2 modèles dans une vue. La page contient à la fois LoginViewModel
et RegisterViewModel
.
p.ex.
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; }
}
est-ce que je dois faire un autre modèle de vue qui contient ces 2 modèles de vue?
public BigViewModel
{
public LoginViewModel LoginViewModel{get; set;}
public RegisterViewModel RegisterViewModel {get; set;}
}
j'ai besoin que les attributs de validation soient avancés à la vue, c'est pourquoi j'ai besoin des modèles de vue.
N'y a - t-il pas une autre voie telle que (sans la 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)
}
10 réponses
Il y a beaucoup de façons...
-
avec votre BigViewModel vous faites:
@model BigViewModel @using(Html.BeginForm()) { @Html.EditorFor(o => o.LoginViewModel.Email) ... }
-
vous pouvez créer 2 vues supplémentaires
Login.CSHTML
@model ViewModel.LoginViewModel @using (Html.BeginForm("Login", "Auth", FormMethod.Post)) { @Html.TextBoxFor(model => model.Email) @Html.PasswordFor(model => model.Password) }
et enregistrer.CSHTML même chose
après la création vous devez les rendre dans la vue principale et leur passer le viewmodel / viewdata
donc ça pourrait être comme ça:
@{Html.RenderPartial("login", ViewBag.Login);} @{Html.RenderPartial("register", ViewBag.Register);}
ou
@{Html.RenderPartial("login", Model.LoginViewModel)} @{Html.RenderPartial("register", Model.RegisterViewModel)}
-
utilisation de parties ajax de votre site web devenir plus indépendant
-
iframes
, mais ce n'est probablement pas le cas
je recommande d'utiliser Html.RenderAction
et PartialViewResults pour accomplir ceci; il vous permettra d'afficher les mêmes données, mais chaque vue partielle aurait encore un modèle de vue unique et supprime la nécessité d'un BigViewModel
donc votre vue contient quelque chose comme ce qui suit:
@Html.RenderAction("Login")
@Html.RenderAction("Register")
où Login
et Register
sont deux actions dans votre contrôleur définies comme suit:
public PartialViewResult Login( )
{
return PartialView( "Login", new LoginViewModel() );
}
public PartialViewResult Register( )
{
return PartialView( "Register", new RegisterViewModel() );
}
les Login
& Register
seraient alors des commandes utilisateur résidant soit dans le dossier de vue courant, soit dans le dossier partagé et souhaiteraient quelque chose comme ceci:
/Views/Shared / Login.cshtml: (ou /Vues/Mavue/Login.cshtml)
@model LoginViewModel
@using (Html.BeginForm("Login", "Auth", FormMethod.Post))
{
@Html.TextBoxFor(model => model.Email)
@Html.PasswordFor(model => model.Password)
}
/Views/Shared/S'Inscrire.cshtml: (ou /Vues/Mavue/s'Inscrire.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)
}
et là vous avez une seule action de contrôleur, vue et fichier de vue pour chaque action avec chacun totalement distinct et ne dépendant pas l'un de l'autre pour quoi que ce soit.
une Autre façon est d'utiliser:
@model Tuple<LoginViewModel,RegisterViewModel>
j'ai expliqué comment utiliser cette méthode à la fois dans la vue et le contrôleur pour un autre exemple: deux modèles dans une vue dans ASP MVC 3
dans votre cas, vous pouvez l'implémenter en utilisant le code suivant:
dans la vue:
@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"})
}
Note que j'ai changé manuellement les attributs du nom pour chaque propriété lors de la construction du formulaire. Cela doit être fait, sinon il ne serait pas correctement mappé au paramètre de la méthode du modèle de type lorsque les valeurs sont envoyées à la méthode associée pour le traitement. Je suggère d'utiliser des méthodes distinctes pour traiter ces formulaires séparément, pour cet exemple, J'ai utilisé les méthodes Login1 et Login2. La méthode Login1 nécessite d'avoir un paramètre de type RegisterViewModel et Login2 nécessite un paramètre de type LoginViewModel.
si un actionlink est vous pouvez utiliser:
@Html.ActionLink("Edit", "Edit", new { id=Model.Item1.Id })
dans la méthode du contrôleur pour la vue, une variable de type Tuple doit être créée puis transmise à la vue.
exemple:
public ActionResult Details()
{
var tuple = new Tuple<LoginViewModel, RegisterViewModel>(new LoginViewModel(),new RegisterViewModel());
return View(tuple);
}
ou vous pouvez remplir les deux instances de LoginViewModel et RegisterViewModel avec des valeurs et les passer ensuite à la vue.
utiliser un modèle de vue qui contient plusieurs modèles de vue:
namespace MyProject.Web.ViewModels
{
public class UserViewModel
{
public UserDto User { get; set; }
public ProductDto Product { get; set; }
public AddressDto Address { get; set; }
}
}
de votre point De vue:
@model MyProject.Web.ViewModels.UserViewModel
@Html.LabelFor(model => model.User.UserName)
@Html.LabelFor(model => model.Product.ProductName)
@Html.LabelFor(model => model.Address.StreetName)
ai-je besoin de faire une autre vue qui tient ces 2 vues?
Réponse: Non
N'y a-t-il pas une autre voie telle que (sans le modèle Bigview):
Oui , vous pouvez utiliser Tuple (apporte la magie en vue d'avoir plusieurs modèles).
Code:
@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)
}
ajouter ce module de collecte.cs à vos Modèles
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)];
}
}
}
contrôleur:
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);
}
}
Le Point De Vue:
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
une façon simple de le faire
on peut l'appeler tout premier modèle
@using project.Models
puis envoyer votre modèle avec viewbag
// for list
ViewBag.Name = db.YourModel.ToList();
// for one
ViewBag.Name = db.YourModel.Find(id);
et en vue
// for list
List<YourModel> Name = (List<YourModel>)ViewBag.Name ;
//for one
YourModel Name = (YourModel)ViewBag.Name ;
alors facilement utiliser ce modèle comme
je veux dire que ma solution était comme la réponse fournie sur cette page de débordement de piles: ASP.NET MVC 4, plusieurs modèles dans une vue?
cependant, dans mon cas, la requête linq qu'ils ont utilisée dans leur contrôleur ne fonctionnait pas pour moi.
Ce qui est dit de la requête:
var viewModels =
(from e in db.Engineers
select new MyViewModel
{
Engineer = e,
Elements = e.Elements,
})
.ToList();
par conséquent," à votre avis, il suffit de préciser que vous utilisez une collection de modèles de vue " n'a pas fonctionné pour moi non plus.
cependant, une légère variation sur cette solution a fonctionné pour moi. Voici ma solution au cas où cela aiderait quelqu'un.
Voici mon modèle de vue dans lequel je sais que je n'aurai qu'une seule équipe mais que cette équipe peut avoir plusieurs cartes (et j'ai un dossier ViewModels dans mon dossier Models btw, d'où le namespace):
namespace TaskBoard.Models.ViewModels
{
public class TeamBoards
{
public Team Team { get; set; }
public List<Board> Boards { get; set; }
}
}
Voici mon contrôleur. C'est la différence la plus importante de la solution dans le lien référencé surtout. Je construis le modèle de vue pour envoyer à la vue différemment.
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);
}
Alors à mon avis je ne le précisez pas comme une liste. Je fais juste " @model TaskBoard.Modèle.Viewmodel.TeamBoards " ensuite, je n'ai besoin de a pour chacun que lorsque je itère sur les conseils d'administration de l'équipe. Voici mon point de vue:
@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>
je suis assez nouveau à ASP.NET MVC donc il m'a fallu un peu de temps pour comprendre cela. Donc, j'espère que ce post aidera quelqu'un à le comprendre pour leur projet dans des délais plus courts calendrier. :- )
-
créez une nouvelle classe dans votre modèle et les propriétés de
LoginViewModel
etRegisterViewModel
:public class UserDefinedModel() { property a1 as LoginViewModel property a2 as RegisterViewModel }
-
puis utilisez
UserDefinedModel
à votre avis.
vous pouvez toujours passer le second objet dans un ViewBag ou voir des données.