web-dev-qa-db-fra.com

Deux modèles dans une vue dans ASP MVC 3

J'ai 2 modèles:

public class Person
{
    public int PersonID { get; set; }
    public string PersonName { get; set; }
}
public class Order
{
    public int OrderID { get; set; }
    public int TotalSum { get; set; }
}

Je veux éditer des objets des DEUX classes en vue UNIQUE. J'ai donc besoin de quelque chose comme:

@model _try2models.Models.Person
@model _try2models.Models.Order

@using(Html.BeginForm())
{
    @Html.EditorFor(x => x.PersonID)
    @Html.EditorFor(x => x.PersonName)
    @Html.EditorFor(x=>x.OrderID)
    @Html.EditorFor(x => x.TotalSum)
}

Bien entendu, cela ne fonctionne pas: une seule instruction 'modèle' est autorisée dans un fichier .cshtml. Peut-être y a-t-il une solution de contournement?

90
Smarty

Créez un modèle de vue parent contenant les deux modèles.

public class MainPageModel{
    public Model1 Model1{get; set;}
    public Model2 Model2{get; set;}
}

De cette façon, vous pouvez ajouter des modèles supplémentaires à une date ultérieure avec un minimum d'effort.

111
Andrew

Pour utiliser le tuple, vous devez procéder comme suit: dans la vue, modifiez le modèle en:

@model Tuple<Person,Order>

pour utiliser les méthodes @html, vous devez effectuer les opérations suivantes:

@Html.DisplayNameFor(Tuple => Tuple.Item1.PersonId)

ou

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

Item1 indique le premier paramètre transmis à la méthode Tuple et vous pouvez utiliser Item2 pour accéder au deuxième modèle, etc.

dans votre contrôleur, vous devez créer une variable de type Tuple puis la transmettre à la vue:

    public ActionResult Details(int id = 0)
    {
        Person person = db.Persons.Find(id);
        if (person == null)
        {
            return HttpNotFound();
        }
        var Tuple = new Tuple<Person, Order>(person,new Order());

        return View(Tuple);
    }

Autre exemple: Plusieurs modèles dans une vue

50
Hamid Tavakoli

Une autre option qui n’a pas besoin de créer un modèle personnalisé est d’utiliser un Tuple <> .

@model Tuple<Person,Order>

Ce n'est pas aussi propre que de créer une nouvelle classe qui contient les deux, selon la réponse d'Andi, mais c'est viable.

48
Bobson

Si vous êtes fan des modèles très plats, vous devez créer un modèle spécifique à cette vue, juste pour supporter la vue ...

public class EditViewModel
    public int PersonID { get; set; }
    public string PersonName { get; set; }
    public int OrderID { get; set; }
    public int TotalSum { get; set; }
}

De nombreuses personnes utilisent AutoMapper pour mapper leurs objets de domaine vers leurs vues à plat.

L'idée du modèle de vue est qu'il ne fait que soutenir la vue - rien d'autre. Vous en avez un par vue pour vous assurer qu'il ne contient que ce qui est requis pour cette vue, pas les charges de propriétés que vous souhaitez pour d'autres vues.

10
Fenton

ok, tout le monde a du sens et j'ai pris toutes les pièces et les ai mises ici pour aider les débutants comme moi qui ont besoin d'explications de bout en bout.

Vous faites votre grande classe qui détient 2 classes, comme indiqué dans la réponse de @ Andrew.

public class teamBoards{
    public Boards Boards{get; set;}
    public Team Team{get; set;}
}

Ensuite, dans votre contrôleur, vous remplissez les 2 modèles. Parfois, il vous suffit de remplir un seul. Ensuite, dans le retour, vous référencez le grand modèle et les 2 intérieurs s’en iront dans la vue.

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

 return View(teamBoards);

Au sommet de la vue

@model yourNamespace.Models.teamBoards

Chargez ensuite vos entrées ou vos affichages en vous référant au gros contenu des modèles:

 @Html.EditorFor(m => Model.Board.yourField)
 @Html.ValidationMessageFor(m => Model.Board.yourField, "", new { @class = "text-danger-yellow" })

 @Html.EditorFor(m => Model.Team.yourField)
 @Html.ValidationMessageFor(m => Model.Team.yourField, "", new { @class = "text-danger-yellow" })

Et. . . .back au ranch, quand la poste entre, référence la grande classe:

 public ActionResult ContactNewspaper(teamBoards teamboards)

et utiliser ce que le ou les modèles ont renvoyé:

string yourVariable = teamboards.Team.yourField;

Vous avez probablement des éléments de validation DataAnnotation dans la classe et mettez probablement if (ModelState.IsValid) en haut du bloc de sauvegarde/modification. . .

5
JustJohn

En fait, il existe un moyen d'utiliser deux modèles ou plus sur une vue sans les envelopper dans une classe contenant les deux.

Employé comme exemple de modèle:

@model Employee

Est effectivement traité comme.

@{ var Model = ViewBag.model as Employee; }

La méthode View (employee) définit donc votre modèle sur le ViewBag, puis le ViewEngine le lance.

Cela signifie que,

ViewBag.departments = GetListOfDepartments();
    return View(employee);

Peut être utilisé comme

            @model  Employee
        @{
                var DepartmentModel = ViewBag.departments as List<Department>;
        }

Pour l'essentiel, vous pouvez utiliser tout ce qui se trouve dans votre ViewBag en tant que "modèle", car c'est ainsi que cela fonctionne. Je ne dis pas que c'est idéal sur le plan architectural, mais c'est possible.

4
Alex Tselevich

Créez simplement un modèle avec une vue contenant toutes les informations nécessaires. Normalement, je crée un modèle pour chaque vue afin que je puisse être spécifique à chaque vue, que ce soit ou créer un modèle parent et en hériter. OR créez un modèle qui inclut les deux vues.

Personnellement, je les ajouterais dans un seul modèle, mais c'est comme cela que je le fais:

public class xViewModel
{
    public int PersonID { get; set; }
    public string PersonName { get; set; }
    public int OrderID { get; set; }
    public int TotalSum { get; set; }
}

@model project.Models.Home.xViewModel

@using(Html.BeginForm())
{
    @Html.EditorFor(x => x.PersonID)
    @Html.EditorFor(x => x.PersonName)
    @Html.EditorFor(x => x.OrderID)
    @Html.EditorFor(x => x.TotalSum)
}
3
Michael

Vous pouvez utiliser le modèle de présentation http://martinfowler.com/eaaDev/PresentationModel.html

Ce modèle de présentation "View" peut contenir à la fois une personne et un ordre, ce nouveau
class peut être le modèle de vos vues.

1
James Kyburz

vous ne pouvez pas déclarer deux modèles sur une vue, essayez d'utiliser Html.Action("Person", "[YourController]") & Html.Action("Order", "[YourController]").

Bonne chance.

0
Jimmy Mac

Outre un modèle de vue dans asp.net, vous pouvez également créer plusieurs vues partielles et affecter différentes vues de modèle à chaque vue, par exemple:

   @{
        Layout = null;
    }

    @model Person;

    <input type="text" asp-for="PersonID" />
    <input type="text" asp-for="PersonName" />

puis une autre vue partielle Modèle pour modèle d'ordre

    @{
        Layout = null;
     }

    @model Order;

    <input type="text" asp-for="OrderID" />
    <input type="text" asp-for="TotalSum" />

puis dans votre vue principale charger les deux vue partielle par

<partial name="PersonPartialView" />
<partial name="OrderPartialView" />
0
shojaeddin

Une autre manière dont on ne parle jamais est de créer une vue dans MSSQL avec toutes les données que vous souhaitez présenter. Ensuite, utilisez LINQ to SQL ou autre chose pour le mapper. Dans votre contrôleur, retournez-le à la vue. Terminé.

0
hidden