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)
 }
267
demandé sur Barrosy 2011-01-22 00:33:37

10 réponses

Il y a beaucoup de façons...

  1. avec votre BigViewModel vous faites:

    @model BigViewModel    
    @using(Html.BeginForm()) {
        @Html.EditorFor(o => o.LoginViewModel.Email)
        ...
    }
    
  2. 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)}
    
  3. utilisation de parties ajax de votre site web devenir plus indépendant

  4. iframes , mais ce n'est probablement pas le cas

247
répondu Omu 2013-10-04 17:40:46

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

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.

116
répondu TheRightChoyce 2011-01-22 21:19:19

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.

96
répondu Hamid 2017-05-23 11:47:17

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)
17
répondu Yini 2016-09-04 22:59:01

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)
     }
8
répondu VCody 2016-01-28 16:30:56

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
3
répondu Morten Frederiksen 2016-08-27 07:01:14

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

1
répondu Pnsadeghy 2013-11-16 16:44:13

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. :- )

1
répondu Notso 2017-05-23 11:55:06
  1. créez une nouvelle classe dans votre modèle et les propriétés de LoginViewModel et RegisterViewModel :

    public class UserDefinedModel() 
    {
        property a1 as LoginViewModel 
        property a2 as RegisterViewModel 
    }
    
  2. puis utilisez UserDefinedModel à votre avis.

1
répondu Andrew 2015-05-16 18:10:47

vous pouvez toujours passer le second objet dans un ViewBag ou voir des données.

1
répondu Nada N. Hantouli 2018-02-27 12:28:26