it-swarm.com.de

Was ist ViewModel in MVC?

Ich bin neu bei ASP.NET MVC. Ich habe ein Problem damit, den Zweck eines ViewModels zu verstehen. 

Was ist ein ViewModel und warum benötigen wir ein ViewModel für eine ASP.NET-MVC-Anwendung? 

Es ist besser, wenn ich ein einfaches Beispiel haben kann.

376
unique

Ein view model steht für die Daten, die Sie in Ihrer Ansicht/Seite anzeigen möchten, unabhängig davon, ob diese für statischen Text oder für Eingabewerte (wie Textfelder und Dropdown-Listen) verwendet werden, die zur Datenbank hinzugefügt (oder bearbeitet) werden können. Es ist etwas anderes als Ihr domain model. Es ist ein Modell für die Ansicht.

Angenommen, Sie verfügen über eine Employee-Klasse, die Ihr Mitarbeiterdomänenmodell darstellt und die folgenden Eigenschaften (eindeutige Kennung, Vorname, Nachname und Erstellungsdatum) enthält:

public class Employee : IEntity
{
     public int Id { get; set; }

     public string FirstName { get; set; }

     public string LastName { get; set; }

     public DateTime DateCreated { get; set; }
}

Ansichtsmodelle unterscheiden sich von Domänenmodellen darin, dass Modelle nur die Daten enthalten (durch Eigenschaften dargestellt), die Sie in Ihrer Ansicht verwenden möchten. Angenommen, Sie möchten einen neuen Mitarbeiterdatensatz hinzufügen, könnte Ihr Ansichtsmodell folgendermaßen aussehen:

public class CreateEmployeeViewModel
{
     public string FirstName { get; set; }

     public string LastName { get; set; }
}

Wie Sie sehen, enthält es nur zwei Eigenschaften. Diese beiden Eigenschaften befinden sich auch im Mitarbeiterdomänenmodell. Warum fragst du das? Id wurde möglicherweise nicht in der Ansicht festgelegt. Möglicherweise wird sie automatisch von der Employee-Tabelle generiert. DateCreated kann auch in der gespeicherten Prozedur oder in der Service-Schicht Ihrer Anwendung festgelegt werden. Daher werden Id und DateCreated im Ansichtsmodell nicht benötigt. Möglicherweise möchten Sie diese beiden Eigenschaften anzeigen, wenn Sie die Details eines Mitarbeiters (einen bereits erfassten Mitarbeiter) als statischen Text anzeigen.

Wenn Sie die Ansicht/Seite laden, erstellt die Methode zum Erstellen von Aktionen in Ihrem Mitarbeitercontroller eine Instanz dieses Ansichtsmodells, füllt ggf. Felder aus und übergibt dieses Ansichtsmodell an die Ansicht/Seite:

public class EmployeeController : Controller
{
     private readonly IEmployeeService employeeService;

     public EmployeeController(IEmployeeService employeeService)
     {
          this.employeeService = employeeService;
     }

     public ActionResult Create()
     {
          CreateEmployeeViewModel model = new CreateEmployeeViewModel();

          return View(model);
     }

     public ActionResult Create(CreateEmployeeViewModel model)
     {
          // Do what ever needs to be done before adding the employee to the database
     }
}

Ihre Ansicht/Seite könnte so aussehen (vorausgesetzt, Sie verwenden ASP.NET MVC und die View Engine Razor):

@model MyProject.Web.ViewModels.CreateEmployeeViewModel

<table>
     <tr>
          <td><b>First Name:</b></td>
          <td>@Html.TextBoxFor(m => m.FirstName, new { maxlength = "50", size = "50" })
              @Html.ValidationMessageFor(m => m.FirstName)
          </td>
     </tr>
     <tr>
          <td><b>Last Name:</b></td>
          <td>@Html.TextBoxFor(m => m.LastName, new { maxlength = "50", size = "50" })
              @Html.ValidationMessageFor(m => m.LastName)
          </td>
     </tr>
</table>

Die Validierung würde daher nur für FirstName und LastName erfolgen. Verwenden Sie Fluent Validation Sie haben möglicherweise eine Validierung wie folgt:

public class CreateEmployeeViewModelValidator : AbstractValidator<CreateEmployeeViewModel>
{
     public CreateEmployeeViewModelValidator()
     {
          RuleFor(m => m.FirstName)
               .NotEmpty()
               .WithMessage("First name required")
               .Length(1, 50)
               .WithMessage("First name must not be greater than 50 characters");

          RuleFor(m => m.LastName)
               .NotEmpty()
               .WithMessage("Last name required")
               .Length(1, 50)
               .WithMessage("Last name must not be greater than 50 characters");
     }
}

Und mit Data Annotations könnte es so aussehen:

public class CreateEmployeeViewModel : ViewModelBase
{
    [Display(Name = "First Name")]
    [Required(ErrorMessage = "First name required")]
    public string FirstName { get; set; }

    [Display(Name = "Last Name")]
    [Required(ErrorMessage = "Last name required")]
    public string LastName { get; set; }
}

Wichtig ist, dass das Ansichtsmodell nur die Daten darstellt, die Sie verwenden möchten, nichts anderes. Sie können sich den gesamten unnötigen Code und die Validierung vorstellen, wenn Sie ein Domänenmodell mit 30 Eigenschaften haben und nur einen einzelnen Wert aktualisieren möchten. In diesem Szenario haben Sie nur diesen einen Wert/diese Eigenschaft im Ansichtsmodell und nicht alle Eigenschaften, die sich im Domänenobjekt befinden.

Ein Ansichtsmodell enthält möglicherweise nicht nur Daten aus einer Datenbanktabelle. Es kann Daten aus einer anderen Tabelle kombinieren. Nehmen Sie mein Beispiel oben, um einen neuen Mitarbeiterdatensatz hinzuzufügen. Sie können neben dem Vor- und Nachnamen auch die Abteilung des Mitarbeiters hinzufügen. Diese Liste der Abteilungen stammt aus Ihrer Tabelle Departments. Jetzt haben Sie Daten aus den Tabellen Employees und Departments in einem Ansichtsmodell. Sie müssen dann nur noch die folgenden beiden Eigenschaften zu Ihrem Ansichtsmodell hinzufügen und Daten mit Daten füllen:

public int DepartmentId { get; set; }

public IEnumerable<Department> Departments { get; set; }

Bei der Bearbeitung von Mitarbeiterdaten (ein Mitarbeiter, der bereits zur Datenbank hinzugefügt wurde), würde sich dies nicht wesentlich von meinem obigen Beispiel unterscheiden. Erstellen Sie ein Ansichtsmodell, nennen Sie es beispielsweise EditEmployeeViewModel. Verfügen Sie nur über die Daten, die Sie bearbeiten möchten, wie zum Beispiel Vorname und Nachname. Bearbeiten Sie die Daten und klicken Sie auf die Schaltfläche "Senden". Das Feld Id macht mir keine großen Sorgen, da der Wert Id wahrscheinlich in der URL enthalten ist. Beispiel: 

http://www.yourwebsite.com/Employee/Edit/3

Nehmen Sie dieses Id und geben Sie es zusammen mit Ihrem Vor- und Nachnamenwert an Ihre Repository-Ebene weiter.

Beim Löschen eines Datensatzes verfolge ich normalerweise den gleichen Pfad wie beim Bearbeitungsansichtsmodell. Ich hätte auch eine URL, zum Beispiel:

http://www.yourwebsite.com/Employee/Delete/3

Wenn die Ansicht zum ersten Mal geladen wird, würde ich die Daten des Mitarbeiters mit Id von 3 aus der Datenbank abrufen. Ich würde dann nur statischen Text in meiner Ansicht/Seite anzeigen, damit der Benutzer sehen kann, welcher Mitarbeiter gelöscht wird. Wenn der Benutzer auf die Schaltfläche "Löschen" klickt, würde ich einfach den Id-Wert von 3 verwenden und ihn an meine Repository-Schicht übergeben. Sie brauchen nur Id, um einen Datensatz aus der Tabelle zu löschen.

Ein weiterer Punkt: Sie brauchen nicht wirklich für jede Aktion ein Ansichtsmodell. Wenn es sich um einfache Daten handelt, ist es in Ordnung, nur EmployeeViewModel zu verwenden. Wenn es sich um komplexe Ansichten/Seiten handelt und diese sich voneinander unterscheiden, würde ich vorschlagen, dass Sie separate Ansichtsmodelle für jede verwenden.

Ich hoffe, dass dadurch jegliche Verwirrung gelöst wird, die Sie hinsichtlich Ansichtsmodellen und Domänenmodellen hatten.

548
Brendan Vogt

Ansichtsmodell ist eine Klasse, die das in einer bestimmten Ansicht verwendete Datenmodell darstellt. Wir könnten diese Klasse als Modell für eine Login-Seite verwenden:

public class LoginPageVM
{
    [Required(ErrorMessage = "Are you really trying to login without entering username?")]
    [DisplayName("Username/e-mail")]
    public string UserName { get; set; }
    [Required(ErrorMessage = "Please enter password:)")]
    [DisplayName("Password")]
    public string Password { get; set; }
    [DisplayName("Stay logged in when browser is closed")]
    public bool RememberMe { get; set; }
}

Mit diesem Ansichtsmodell können Sie die Ansicht definieren (Razor View Engine):

@model CamelTrap.Models.ViewModels.LoginPageVM

@using (Html.BeginForm()) {
    @Html.EditorFor(m => m);
    <input type="submit" value="Save" class="submit" />
}

Und Aktionen:

[HttpGet]
public ActionResult LoginPage()
{
    return View();
}

[HttpPost]
public ActionResult LoginPage(LoginPageVM model)
{
    ...code to login user to application...
    return View(model);
}

Was zu diesem Ergebnis führt (Bildschirm wird nach dem Absenden des Formulars mit Validierungsnachrichten erstellt):

Wie Sie sehen, hat ein Ansichtsmodell viele Rollen:

  • Ansichtsmodelle dokumentieren eine Ansicht, indem sie nur Felder enthalten, die in der Ansicht dargestellt werden.
  • Ansichtsmodelle können bestimmte Validierungsregeln enthalten, die Datenanmerkungen oder IDataErrorInfo verwenden.
  • Das Ansichtsmodell definiert, wie eine Ansicht aussehen soll (für LabelFor, EditorFor, DisplayFor Helfer).
  • Ansichtsmodelle können Werte aus verschiedenen Datenbankentitäten kombinieren.
  • Sie können Vorlagen für Ansichtsmodelle einfach angeben und mithilfe der Hilfe von DisplayFor oder EditorFor an vielen Stellen wiederverwenden.

Ein anderes Beispiel für ein Ansichtsmodell und dessen Abfrage: Wir möchten grundlegende Benutzerdaten, seine Privilegien und den Benutzernamen anzeigen. Wir erstellen ein spezielles Ansichtsmodell, das nur die erforderlichen Felder enthält. Wir rufen Daten von verschiedenen Entitäten aus der Datenbank ab, die Ansicht kennt jedoch nur die Ansichtsmodellklasse:

public class UserVM {
    public int ID { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public bool IsAdministrator { get; set; }
    public string MothersName { get; set; }
}

Abruf:

var user = db.userRepository.GetUser(id);

var model = new UserVM() {
   ID = user.ID,
   FirstName = user.FirstName,
   LastName = user.LastName,
   IsAdministrator = user.Proviledges.IsAdministrator,
   MothersName = user.Mother.FirstName + " " + user.Mother.LastName
} 
126
LukLed

Bearbeiten: Ich habe diese Antwort in meinem Blog aktualisiert:

http://www.samwheat.com/Post/The-function-of-ViewModels-in-MVC-web-development

Meine Antwort ist etwas langwierig, aber ich halte es für wichtig, Ansichtsmodelle mit anderen häufig verwendeten Modellen zu vergleichen, um zu verstehen, warum sie sich unterscheiden und warum sie notwendig sind.

Um zusammenzufassen und die gestellte Frage direkt zu beantworten:

Im Allgemeinen ist ein Ansichtsmodell ein Objekt, das alle zum Rendern einer Ansicht erforderlichen Eigenschaften und Methoden enthält. Eigenschaften von Ansichtsmodellen beziehen sich häufig auf Datenobjekte wie Kunden und Aufträge. Außerdem enthalten sie Eigenschaften, die sich auf die Seite oder die Anwendung selbst beziehen, wie z Erstellen Sie eine HTML-Seite. Einer der vielen Gründe für die Verwendung eines Ansichtsmodells besteht darin, dass Ansichtsmodelle eine Möglichkeit zum Komponententest bestimmter Präsentationsaufgaben bieten, z.

Hier finden Sie einen Vergleich von Entitätsmodellen (a.ka. DTOs a.ka.-Modelle), Präsentationsmodellen und Ansichtsmodellen.

Datenübertragungsobjekte a.k.a “Modell”

Ein Data Transfer Object (DTO) ist eine Klasse mit Eigenschaften, die einem Tabellenschema in einer Datenbank entsprechen. DTOs werden nach ihrer allgemeinen Verwendung für den Transport von Daten zu und von einem Datenspeicher benannt.
Merkmale von DTOs:

• Sind Geschäftsobjekte - Ihre Definition hängt von den Anwendungsdaten ab.

• Enthält normalerweise nur Eigenschaften - kein Code.

• Wird hauptsächlich zum Transportieren von Daten zu und von einer Datenbank verwendet.

• Eigenschaften stimmen genau oder genau mit Feldern in einer bestimmten Tabelle in einem Datenspeicher überein.

Datenbanktabellen werden normalerweise normalisiert, daher werden DTOs normalerweise auch normalisiert. Dies macht sie für die Präsentation von Daten nur eingeschränkt nutzbar. Für bestimmte einfache Datenstrukturen sind sie jedoch häufig recht gut geeignet.

Hier sind zwei Beispiele, wie DTOs aussehen könnten:

public class Customer
{
    public int ID { get; set; }
    public string CustomerName { get; set; }
}


public class Order
{
    public int ID { get; set; }
    public int CustomerID { get; set; }
    public DateTime OrderDate { get; set; }
    public Decimal OrderAmount { get; set; }
}

Präsentationsmodelle

Ein Präsentationsmodell ist eine Utility Klasse, die zum Rendern von Daten auf einem Bildschirm oder in einem Bericht verwendet wird. Präsentationsmodelle werden in der Regel verwendet, um komplexe Datenstrukturen zu modellieren, die aus Daten mehrerer DTOs bestehen. Präsentationsmodelle repräsentieren häufig eine denormalisierte Ansicht von Daten.

Eigenschaften von Präsentationsmodellen:

• Sind Geschäftsobjekte - Ihre Definition hängt von den Anwendungsdaten ab.

• Enthält hauptsächlich Eigenschaften. Code ist normalerweise auf das Formatieren von Daten oder das Konvertieren in oder aus einem DTO beschränkt. Präsentationsmodelle sollten keine Geschäftslogik enthalten.

• Präsentieren Sie häufig eine denormalisierte Ansicht von Daten. Das heißt, sie kombinieren häufig Eigenschaften mehrerer DTOs.

• Enthalten häufig Eigenschaften eines anderen Basistyps als ein DTO. Beispielsweise können Dollarbeträge als Zeichenfolgen dargestellt werden, sodass sie Kommas und ein Währungssymbol enthalten können.

• Oftmals definiert durch die Art und Weise, wie sie verwendet werden, sowie durch ihre Objektmerkmale. Mit anderen Worten, ein einfaches DTO, das als Hintergrundmodell für das Rendern eines Rasters verwendet wird, ist in der Tat auch ein Präsentationsmodell im Kontext dieses Rasters.

Präsentationsmodelle werden "nach Bedarf" und "nach Bedarf" verwendet (während DTOs normalerweise an das Datenbankschema gebunden sind). Ein Präsentationsmodell kann verwendet werden, um Daten für eine gesamte Seite, ein Raster auf einer Seite oder ein Dropdown auf einem Raster auf einer Seite zu modellieren. Präsentationsmodelle enthalten häufig Eigenschaften, die andere Präsentationsmodelle sind. Präsentationsmodelle sind häufig für den einmaligen Gebrauch konzipiert, um beispielsweise ein bestimmtes Raster auf einer einzelnen Seite zu rendern.

Ein Beispiel für ein Präsentationsmodell:

public class PresentationOrder
{
    public int OrderID { get; set; }
    public DateTime OrderDate { get; set; }
    public string PrettyDate { get { return OrderDate.ToShortDateString(); } }
    public string CustomerName { get; set; }
    public Decimal OrderAmount { get; set; }
    public string PrettyAmount { get { return string.Format("{0:C}", OrderAmount); } }
}

Modelle anzeigen

Ein Ansichtsmodell ähnelt einem Präsentationsmodell, in dem es sich um eine Hintergrundklasse zum Rendern einer Ansicht handelt. Es unterscheidet sich jedoch stark von einem Präsentationsmodell oder einem DTO in seiner Konstruktion. Ansichtsmodelle enthalten häufig dieselben Eigenschaften wie Präsentationsmodelle und DTOs. Aus diesem Grund werden sie häufig verwechselt.

Merkmale der Ansichtsmodelle:

• Sind die einzige Datenquelle, die zum Rendern einer Seite oder eines Bildschirms verwendet wird. Normalerweise bedeutet dies, dass ein Ansichtsmodell alle Eigenschaften verfügbar macht, die ein Steuerelement auf der Seite benötigt, um sich selbst korrekt zu rendern. Indem Sie das Ansichtsmodell zur einzigen Datenquelle für die Ansicht machen, verbessern Sie seine Fähigkeit und seinen Wert für Komponententests erheblich.

• Sind zusammengesetzte Objekte , die Eigenschaften enthalten, die aus Anwendungsdaten bestehen, sowie Eigenschaften, die vom Anwendungscode verwendet werden. Diese Eigenschaft ist für das Design des Ansichtsmodells für die Wiederverwendbarkeit von entscheidender Bedeutung und wird in den folgenden Beispielen erläutert.

• Anwendungscode enthalten. Ansichtsmodelle enthalten normalerweise Methoden, die während des Renderns und der Interaktion des Benutzers mit der Seite aufgerufen werden. Dieser Code bezieht sich normalerweise auf die Ereignisbehandlung, die Animation, die Sichtbarkeit von Steuerelementen, das Styling usw.

• Enthalten Sie Code, der Geschäftsdienste aufruft, um Daten abzurufen oder an einen Datenbankserver zu senden. Dieser Code wird häufig fälschlicherweise in eine Steuerung eingefügt. Das Aufrufen von Geschäftsservices von einem Controller aus schränkt normalerweise die Nützlichkeit des Ansichtsmodells für Komponententests ein. Im Klartext sollten Ansichtsmodelle selbst keine Geschäftslogik enthalten, sondern Dienste aufrufen, die Geschäftslogik enthalten.

• Enthalten häufig Eigenschaften, die andere Ansichtsmodelle für andere Seiten oder Bildschirme darstellen.

• Werden "pro Seite" oder "pro Bildschirm" geschrieben. Ein eindeutiges Ansichtsmodell wird normalerweise für jede Seite oder jeden Bildschirm in einer Anwendung geschrieben.

• Wird normalerweise von einer Basisklasse abgeleitet, da die meisten Seiten und Bildschirme gemeinsame Eigenschaften haben.

Modellzusammenstellung anzeigen

Wie bereits erwähnt, sind Ansichtsmodelle zusammengesetzte Objekte, da sie Anwendungseigenschaften und Geschäftsdateneigenschaften für ein einzelnes Objekt kombinieren. Beispiele für häufig verwendete Anwendungseigenschaften, die in Ansichtsmodellen verwendet werden, sind:

• Eigenschaften, mit denen der Anwendungsstatus angezeigt wird, z. B. Fehlermeldungen, Benutzername, Status usw.

• Eigenschaften, mit denen Steuerelemente formatiert, angezeigt, stilisiert oder animiert werden.

• Eigenschaften, die für die Datenbindung verwendet werden, z. B. Listenobjekte und Eigenschaften, die vom Benutzer eingegebene Zwischendaten enthalten.

Die folgenden Beispiele zeigen, warum die zusammengesetzte Natur von Ansichtsmodellen wichtig ist und wie wir am besten ein Ansichtsmodell erstellen können, das effizient und wiederverwendbar ist.

Angenommen, wir schreiben eine Webanwendung. Eine der Anforderungen für das Anwendungsdesign besteht darin, dass der Seitentitel, der Benutzername und der Anwendungsname auf jeder Seite angezeigt werden müssen. Wenn wir eine Seite zum Anzeigen eines Präsentationsauftragsobjekts erstellen möchten, können wir das Präsentationsmodell wie folgt ändern:

public class PresentationOrder
{
    public string PageTitle { get; set; }
    public string UserName { get; set; }
    public string ApplicationName { get; set; }
    public int OrderID { get; set; }
    public DateTime OrderDate { get; set; }
    public string PrettyDate { get { return OrderDate.ToShortDateString(); } }
    public string CustomerName { get; set; }
    public Decimal OrderAmount { get; set; }
    public string PrettyAmount { get { return string.Format("{0:C}", OrderAmount); } }
}

Dieses Design könnte funktionieren ... aber was ist, wenn wir eine Seite erstellen möchten, auf der eine Liste der Bestellungen angezeigt wird? Die Eigenschaften "PageTitle", "UserName" und "ApplicationName" werden wiederholt und es wird unhandlich, mit ihnen zu arbeiten. Was ist auch, wenn wir eine Logik auf Seitenebene im Konstruktor der Klasse definieren möchten? Das können wir nicht mehr, wenn wir für jede angezeigte Bestellung eine Instanz erstellen.

Zusammensetzung über Vererbung

Hier ist eine Möglichkeit, das Ordnungspräsentationsmodell neu zu faktorisieren, sodass es zu einem echten Ansichtsmodell wird und nützlich für die Anzeige eines einzelnen PresentationOrder-Objekts oder einer Sammlung von PresentationOrder-Objekten ist:

public class PresentationOrderVM
{
    // Application properties
    public string PageTitle { get; set; }
    public string UserName { get; set; }
    public string ApplicationName { get; set; }

    // Business properties
    public PresentationOrder Order { get; set; }
}


public class PresentationOrderVM
{
    // Application properties
    public string PageTitle { get; set; }
    public string UserName { get; set; }
    public string ApplicationName { get; set; }

    // Business properties
    public List<PresentationOrder> Orders { get; set; }
}

Wenn wir uns die beiden oben genannten Klassen ansehen, können wir feststellen, dass ein Ansichtsmodell ein Präsentationsmodell ist, das ein anderes Präsentationsmodell als Eigenschaft enthält. Das Präsentationsmodell der obersten Ebene (d. H. Ansichtsmodell) enthält Eigenschaften, die für die Seite oder Anwendung relevant sind, während das Präsentationsmodell (Eigenschaft) Eigenschaften enthält, die für Anwendungsdaten relevant sind.

Wir können unseren Entwurf einen Schritt weiter gehen und eine Basisansichtsmodellklasse erstellen, die nicht nur für PresentationOrders, sondern auch für jede andere Klasse verwendet werden kann:

public class BaseViewModel
{
    // Application properties
    public string PageTitle { get; set; }
    public string UserName { get; set; }
    public string ApplicationName { get; set; }
}

Jetzt können wir unsere PresentationOrderVM so vereinfachen:

public class PresentationOrderVM : BaseViewModel
{
    // Business properties
    public PresentationOrder Order { get; set; }
}

public class PresentationOrderVM : BaseViewModel
{
    // Business properties
    public List<PresentationOrder> Orders { get; set; }
}

Wir können unser BaseViewModel noch mehr wiederverwenden, indem wir es generisch machen:

public class BaseViewModel<T>
{
    // Application properties
    public string PageTitle { get; set; }
    public string UserName { get; set; }
    public string ApplicationName { get; set; }

    // Business property
    public T BusinessObject { get; set; }
}

Jetzt sind unsere Implementierungen mühelos:

public class PresentationOrderVM : BaseViewModel<PresentationOrder>
{
    // done!
}

public class PresentationOrderVM : BaseViewModel<List<PresentationOrder>>
{
    // done!
}
76
Sam

Wenn Sie über spezifische Eigenschaften für die Ansicht verfügen und nicht mit DB/Service/Data Store in Zusammenhang stehen, sollten Sie ViewModels verwenden. Angenommen, Sie möchten ein Ankreuzfeld auf der Grundlage eines oder mehrerer DB-Felder aktiviert lassen, das DB-Feld selbst ist jedoch nicht boolean. Es ist zwar möglich, diese Eigenschaften im Modell selbst zu erstellen und für die Bindung an Daten nicht sichtbar zu machen. In Abhängigkeit von der Menge dieser Felder und Transaktionen möchten Sie das Modell möglicherweise nicht überladen.

Wenn zu wenig ansichtsspezifische Daten und/oder Transformationen vorhanden sind, können Sie das Modell selbst verwenden

22
fozylet

Ich habe nicht alle Beiträge gelesen, aber bei jeder Antwort scheint mir ein Konzept zu fehlen, das mir wirklich "geholfen" hat ... 

Wenn ein Modell einer Datenbank ähneltTable, dann ist ein ViewModel einer Datenbank ähnlich.View- Eine View gibt normalerweise entweder kleine Datenmengen aus einer Tabelle zurück oder komplexe Datensätze aus mehreren Tabellen (Joins).

Ich benutze ViewModels, um Informationen in eine Ansicht/ein Formular zu übergeben, und überträgt diese Daten dann in ein gültiges Modell, wenn das Formular an den Controller zurückgesendet wird - auch sehr praktisch zum Speichern von Listen (IEnumerable).

14
halfacreSal

Viele große Beispiele, lassen Sie mich das klar und knackig erklären.

ViewModel = Modell, das erstellt wurde, um die Ansicht zu bedienen.

ASP.NET MVC-Ansicht kann nicht mehr als ein Modell haben. Wenn also Eigenschaften von mehr als einem Modell in der Ansicht angezeigt werden müssen, ist dies nicht möglich. ViewModel dient diesem Zweck.

Ansichtsmodell ist eine Modellklasse, die nur die Eigenschaften enthalten kann, die für eine Ansicht erforderlich sind. Es kann auch Eigenschaften von mehreren Entitäten (Tabellen) der Datenbank enthalten. Wie der Name vermuten lässt, wird dieses Modell speziell für die View-Anforderungen erstellt. 

Nachfolgend finden Sie einige Beispiele für Ansichtsmodelle 

  • Um Daten von mehr als Entitäten auf einer Ansichtsseite aufzulisten, können wir ein Ansichtsmodell erstellen und über Eigenschaften aller Entitäten verfügen, für die wir Daten angeben möchten. Fügen Sie diese Datenbankentitäten hinzu, und legen Sie View modelproperties fest, und kehren Sie zur Ansicht zurück, um Daten verschiedener Entitäten in einer Tabellenform anzuzeigen
  • Das Ansichtsmodell kann nur bestimmte Felder einer einzelnen Entität definieren, die für die Ansicht erforderlich sind.

ViewModel kann auch zum Einfügen und Aktualisieren von Datensätzen in mehreren Entitäten verwendet werden. In ViewModel werden jedoch hauptsächlich Spalten aus mehreren Entitäten (Modell) in einer einzigen Ansicht angezeigt.

Das Erstellen von ViewModel entspricht dem Erstellen von Model. Das Erstellen von Ansichten für das Viewmodel entspricht dem Erstellen von Ansichten für Model.

Hier ist ein kleines Beispiel von Listendaten mit ViewModel .

Hoffe das wird nützlich sein.

10
Sheo Narayan

MVC hat kein Ansichtsmodell: Es hat ein Modell, eine Ansicht und einen Controller. Ein Viewmodel ist Teil von MVVM (Model-View-Viewmodel). MVVM ist vom Präsentationsmodell abgeleitet und in WPF populär. Es sollte auch ein Modell in MVVM geben, aber die meisten Leute verpassen den Punkt dieses Musters vollständig und sie haben nur eine Ansicht und ein Ansichtsmodell. Das Modell in MVC ähnelt dem Modell in MVVM.

In MVC ist der Prozess in 3 verschiedene Verantwortlichkeiten aufgeteilt:

  • View ist für die Präsentation der Daten an den Benutzer verantwortlich
  • Ein Controller ist für den Seitenfluss verantwortlich
  • Ein Modell ist für die Geschäftslogik verantwortlich

MVC ist für Webanwendungen nicht sehr geeignet. Es ist ein von Smalltalk eingeführtes Muster zum Erstellen von Desktop-Anwendungen. Eine Webumgebung verhält sich völlig anders. Es macht wenig Sinn, ein 40 Jahre altes Konzept aus der Desktop-Entwicklung zu kopieren und in eine Web-Umgebung einzufügen. Viele Leute denken jedoch, dass dies in Ordnung ist, da ihre Anwendung die korrekten Werte kompiliert und zurückgibt. Das ist meiner Meinung nach nicht genug, um eine bestimmte Designwahl als ok zu erklären.

Ein Beispiel für ein Modell in einer Webanwendung könnte sein:

public class LoginModel
{
    private readonly AuthenticationService authentication;

    public LoginModel(AuthenticationService authentication)
    {
        this.authentication = authentication;
    }

    public bool Login()
    {
        return authentication.Login(Username, Password);
    }

    public string Username { get; set; }
    public string Password { get; set; }
}

Der Controller kann es so verwenden:

public class LoginController
{
    [HttpPost]
    public ActionResult Login(LoginModel model)
    {
        bool success = model.Login();

        if (success)
        {
            return new RedirectResult("/dashboard");
        }
        else
        {
            TempData["message"] = "Invalid username and/or password";
            return new RedirectResult("/login");
        }
    }
}

Ihre Controller-Methoden und Ihre Modelle sind klein, leicht zu testen und auf den Punkt.

10
Jeroen

Ansichtsmodell a ist eine einfache Klasse, die mehrere Klasseneigenschaften enthalten kann. Wir verwenden es, um alle erforderlichen Eigenschaften zu erben, z. Ich habe zwei Klassen Schüler und Fach 

Public class Student
{
public int Id {get; set;}
public string Name {get; set;}
}  
Public class Subject
{
public int SubjectID {get; set;}
public string SubjectName {get; set;}
}

Jetzt möchten wir die Datensätze des Schülers und des Betreffs in der Ansicht (In MVC) anzeigen. Es ist jedoch nicht möglich, mehr als eine Klasse hinzuzufügen:

 @model ProjectName.Model.Student  
 @model ProjectName.Model.Subject

der Code oben wird einen Fehler auslösen ...

Jetzt erstellen wir eine Klasse und können ihr einen beliebigen Namen geben, aber dieses Format "XyzViewModel" macht es verständlicher. Es ist Vererbungskonzept . Nun erstellen wir eine dritte Klasse mit dem folgenden Namen:

public class StudentViewModel:Subject
{
public int ID {get; set;}
public string Name {get; set;}
}

Jetzt verwenden wir dieses ViewModel in View 

@ model ProjectName.Model.StudentViewModel

Jetzt können wir auf alle Eigenschaften von StudentViewModel und der geerbten Klasse in View zugreifen.

10
Mayank

ViewModel ist ein Workarround, der die konzeptionelle Unbeholfenheit des MVC-Frameworks korrigiert. Es stellt die vierte Schicht in der 3-Schicht-Architektur des Model-View-Controllers dar. Wenn das Modell (Domänenmodell) nicht geeignet ist, zu groß (größer als 2-3 Felder) für die Ansicht, erstellen wir ein kleineres ViewModel, um es an die Ansicht zu übergeben.

6
gsivanov
  • ViewModel enthält Felder, die in der Ansicht dargestellt werden (für LabelFor, EditorFor, DisplayFor-Helfer)
  • ViewModel kann über bestimmte Validierungsregeln verfügen, die Datenanmerkungen Oder IDataErrorInfo verwenden.
  • ViewModel kann mehrere Entitäten oder Objekte aus unterschiedlichen Datenmodellen oder Datenquellen haben.

ViewModel gestalten

public class UserLoginViewModel 
{ 
[Required(ErrorMessage = "Please enter your username")] 
[Display(Name = "User Name")]
[MaxLength(50)]
public string UserName { get; set; }
 [Required(ErrorMessage = "Please enter your password")]
 [Display(Name = "Password")]
 [MaxLength(50)]
 public string Password { get; set; } 
} 

Darstellung des Viewmodels in der Ansicht

@model MyModels.UserLoginViewModel 
@{
 ViewBag.Title = "User Login";
 Layout = "~/Views/Shared/_Layout.cshtml";
}
@using (Html.BeginForm())
{
<div class="editor-label">
 @Html.LabelFor(m => m.UserName)
</div>
<div class="editor-field">
 @Html.TextBoxFor(m => m.UserName)
 @Html.ValidationMessageFor(m => m.UserName)
</div>
<div class="editor-label">
 @Html.LabelFor(m => m.Password)
</div>
<div class="editor-field">
 @Html.PasswordFor(m => m.Password)
 @Html.ValidationMessageFor(m => m.Password)
</div>
<p>
 <input type="submit" value="Log In" />
</p>
</div>
}

Mit Action arbeiten

public ActionResult Login()
{ 
return View();
}
[HttpPost]
public ActionResult Login(UserLoginViewModel user)
{
// To acces data using LINQ
DataClassesDataContext mobjentity = new DataClassesDataContext();
 if (ModelState.IsValid) 
{ 
try
 {
 var q = mobjentity.tblUsers.Where(m => m.UserName == user.UserName && m.Password == user.Password).ToList(); 
 if (q.Count > 0) 
 { 
 return RedirectToAction("MyAccount");
 }
 else
 {
 ModelState.AddModelError("", "The user name or password provided is incorrect.");
 }
 }
 catch (Exception ex)
 {
 } 
 } 
 return View(user);
} 
  1. Fügen Sie in ViewModel nur die Felder/Daten ein, die auf der Ansicht/Seite angezeigt werden sollen.
  2. Da view die Eigenschaften des ViewModels wiedergibt, ist es für _ _ einfach für das Rendern und die Wartung.
  3. Verwenden Sie einen Mapper, wenn ViewModel komplexer wird.
1
wild coder

Ein Ansichtsmodell ist ein konzeptionelles Datenmodell. Seine Verwendung ist beispielsweise, um entweder eine Teilmenge zu erhalten oder Daten aus verschiedenen Tabellen zu kombinieren. 

Möglicherweise möchten Sie nur bestimmte Eigenschaften. Daher können Sie nur diese Eigenschaften und nicht zusätzliche nicht benötigte Eigenschaften laden

1
user6685907

View Model ist eine Klasse, mit der Daten in View gerendert werden können. Angenommen, Sie haben zwei Entitäten, Place und PlaceCategory, und Sie möchten mit einem einzigen Modell auf Daten von beiden Entitäten zugreifen. Dann verwenden wir ViewModel.

  public class Place
    {
       public int PlaceId { get; set; }
        public string PlaceName { get; set; }
        public string Latitude { get; set; }
        public string Longitude { get; set; }
        public string BestTime { get; set; }
    }
    public class Category
    {
        public int ID { get; set; }
        public int? PlaceId { get; set; }
        public string PlaceCategoryName { get; set; }
        public string PlaceCategoryType { get; set; }
    }
    public class PlaceCategoryviewModel
    {
        public string PlaceName { get; set; }
        public string BestTime { get; set; }
        public string PlaceCategoryName { get; set; }
        public string PlaceCategoryType { get; set; }
    }

Im obigen Beispiel sind "Ort" und "Kategorie" die beiden verschiedenen Entitäten, und das Ansichtskodell "PlaceCategory" ist "ViewModel", das wir für View verwenden können.

0
Sagar Shinde