在一个视图中的多个模型

我想在一个视图中有2个模型。 该页面同时包含LoginViewModelRegisterViewModel

例如

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

我是否需要制作另一个包含这两个ViewModel的ViewModel?

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

我需要将validation属性提交给视图,这就是为什么我需要ViewModels。

是不是有另一种方式,如(没有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) } 

有很多方法

  1. 与您的BigViewModel你做:

     @model BigViewModel @using(Html.BeginForm()) { @Html.EditorFor(o => o.LoginViewModel.Email) ... } 
  2. 您可以创build另外2个视图

    Login.cshtml

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

    和register.cshtml 一样的东西

    在创build之后,你必须在主视图中渲染它们,并传递viewmodel / viewdata

    所以可能是这样的:

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

    要么

     @{Html.RenderPartial("login", Model.LoginViewModel)} @{Html.RenderPartial("register", Model.RegisterViewModel)} 
  3. 使用你的网站的Ajax部分变得更加独立

  4. iframes ,但可能情况并非如此

我build议使用Html.RenderAction和PartialViewResults来完成这个; 它将允许你显示相同的数据,但是每个局部视图仍然会有一个单一的视图模型,并且不需要BigViewModel

所以你的观点包含如下内容:

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

LoginRegister都在你的控制器中的行为定义如下:

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

LoginRegister然后将是用户控件驻留在当前的视图文件夹,或在共享文件夹,并希望这样的事情:

/Views/Shared/Login.cshtml :(或/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 :(或/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) } 

在那里你有一个单一的控制器动作,查看和查看每个动作的文件,每个动作完全不同而且不依赖于任何东西。

另一种方法是使用:

 @model Tuple<LoginViewModel,RegisterViewModel> 

我已经解释了如何在视图和控制器中使用这个方法的另一个例子: ASP MVC 3中的一个视图中的两个模型

在你的情况下,你可以使用下面的代码来实现它:

在看法:

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

请注意 ,在构build表单时,我手动更改了每个属性的Name属性。 这需要完成,否则将值发送到关联的方法进行处理时,将无法正确映射到types模型的方法参数。 我会build议使用单独的方法来分别处理这些表单,对于这个例子我使用了Login1和Login2方法。 Login1方法需要有一个RegisterViewModeltypes的参数,而Login2需要一个LoginViewModeltypes的参数。

如果需要动作链接,您可以使用:

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

在控制器的视图方法中,需要创build一个Tupletypes的variables,然后传递给视图。

例:

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

也可以用值填充LoginViewModel和RegisterViewModel的两个实例,然后将其传递给视图。

使用包含多个视图模型的视图模型:

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

在你看来:

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

我是否需要提出另一个观点,持​​有这两个意见?

答:否

是不是有另一种方式,如(没有BigViewModel):

是的 ,你可以使用Tuple(带来多种模式的魔法)。

码:

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

将此ModelCollection.cs添加到您的模型

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

控制器:

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

风景:

 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 

我想说,我的解决scheme就像在这个stackoverflow页面提供的答案: ASP.NET MVC 4,在一个视图中的多个模型?

但是,在我的情况下,他们在他们的控制器中使用的linq查询不适合我。

这就是查询:

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

因此,“在你看来只是指定你使用的视图模型集合”也不适用于我。

然而,这个解决scheme的一个小小的变化对我来说确实有效。 这是我的解决scheme,如果这有助于任何人。

这里是我的视图模型,我知道我将只有一个团队,但该团队可能有多个董事会(我的模型文件夹btw中有一个ViewModels文件夹,因此命名空间):

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

现在这是我的控制器。 这是与上面链接中的解决scheme最显着的区别。 我构build出ViewModel以不同的方式发送到视图。

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

然后在我看来,我没有把它列为一个列表。 我只是做“@model TaskBoard.Models.ViewModels.TeamBoards”然后,我只需要一个每当我迭代团队的董事会。 这是我的看法:

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

我对ASP.NET MVC相当新,所以花了我一点时间来解决这个问题。 所以,我希望这篇文章可以帮助人们在更短的时间内找出自己的项目。 🙂

  1. 在您的模型和LoginViewModelRegisterViewModel属性中创build一个新类:

     public class UserDefinedModel() { property a1 as LoginViewModel property a2 as RegisterViewModel } 
  2. 然后在你的视图中使用UserDefinedModel

一个简单的方法来做到这一点

我们可以先打电话给所有型号

 @using project.Models 

然后用viewbag发送你的模型

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

并在视图中

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

然后轻松使用这个像模型