War es hilfreich?

Lösung

Ich schaffe, was ich ein „Viewmodel“ für jede Ansicht aufrufen. Ich habe sie in einem Ordner namens Viewmodel in meinem MVC Web-Projekt. Ich nenne sie nach dem Controller und die Aktion (oder Ansicht) sie repräsentieren. Also, wenn ich brauche Daten zu übergeben, um die SignUp Blick auf die Mitgliedschaft Controller ich eine MembershipSignUpViewModel.cs Klasse erstellen und legen Sie sie in den Ordner Viewmodels.

Dann füge ich die notwendigen Eigenschaften und Methoden, um die Übertragung von Daten von der Steuerung zur Ansicht zu erleichtern. Ich verwende den AutoMapper von meinem Viewmodel zu dem Domain Model zu bekommen und wieder zurück, wenn nötig.

Das funktioniert auch gut für Verbundviewmodels, die Eigenschaften enthalten, die von der Art der anderen Viewmodels sind. Zum Beispiel, wenn Sie 5-Widgets auf der Indexseite in den Mitgliedschaft-Controller und haben Sie ein Viewmodel für jede Teilansicht - wie geben Sie die Daten aus dem Index Aktion auf die partials? Sie fügen eine Eigenschaft auf den MembershipIndexViewModel vom Typ MyPartialViewModel und wenn die partiellen Rendering würden Sie in Model.MyPartialViewModel passieren.

Doing es auf diese Weise können Sie die Teilansichtsmodell Eigenschaften einzustellen, ohne den Index Ansicht überhaupt zu ändern. Es ist immer noch passiert nur in Model.MyPartialViewModel, so gibt es weniger eine Chance ist, dass man durch die ganze Kette von partials gehen müssen wird, etwas zu reparieren, wenn alles, was Sie tun, eine Eigenschaft zu dem Teilansichtsmodell ist hinzuzufügen.

Ich werde auch den Namensraum „MyProject.Web.ViewModels“ die web.config hinzufügen, um mich zu erlauben, sie in jeder Ansicht zu verweisen, ohne jemals auf jeder Ansicht eine explizite Import-Anweisung hinzufügen. Nur macht es ein wenig sauberer.

Andere Tipps

Die Trennung Klassen nach Kategorie (Controllers, Viewmodel, Filter etc.), ist Unsinn.

Wenn Sie möchten, schreiben Code für den Home-Bereich Ihrer Website (/), dann erstellen Sie einen Ordner mit dem Namen Haus und legen dort die Homecontroller, IndexViewModel, AboutViewModel usw. und alle damit verbundenen Klassen von Heim Aktionen.

Wenn Sie gemeinsam genutzte Klassen haben, wie ein Application, können Sie es an der Wurzel Ihres Projekts setzen können.

Warum getrennte Dinge, die verwandt sind (Homecontroller, IndexViewModel) und die Dinge zusammen, die keine Beziehung zu allen (Homecontroller, Account) haben?


Ich über einen Blog-Eintrag geschrieben dieses Thema.

Ich halte meine Anwendungsklassen in einem Unterverzeichnis namens „Core“ (oder eine separate Klassenbibliothek) und verwendet die gleichen Methoden wie die KIGG Anwendung Probe, aber mit einigen geringfügigen Änderungen meiner Anwendungen mehr DRY machen.

ich eine BaseViewData Klasse in / Kern / Viewdata / wo ich gemeinsam auf alle Eigenschaften gespeichert werden.

Danach hat ich auch alle meine Ansicht Viewdata-Klassen im selben Ordner erstellen, die dann aus BaseViewData ableiten und haben Blick spezifische Eigenschaften.

Dann erstelle ich ein Application, die alle meine Controller von abzuleiten. Die Application hat eine generische GetViewData Methode wie folgt:

protected T GetViewData<T>() where T : BaseViewData, new()
    {
        var viewData = new T
        {
           Property1 = "value1",
           Property2 = this.Method() // in the ApplicationController
        };
        return viewData;
    }

Schließlich Aktion in meinem Controller ich tue folgende zu meinem Viewdata Modell zu bauen

public ActionResult Index(int? id)
    {
        var viewData = this.GetViewData<PageViewData>();
        viewData.Page = this.DataContext.getPage(id); // ApplicationController
        ViewData.Model = viewData;
        return View();
    }

Ich denke, das funktioniert wirklich gut und es hält Ihre Ansichten ordentlich und Ihre Controller dünn.

Eine Ansichtsmodell Klasse gibt es mehrere Stücke von Daten, die von Instanzen von Klassen in einer einzigen, einfach zu verwalten Objekt dargestellt zu kapseln, dass Sie Ihre Ansicht gelangen kann.

in ihren eigenen Dateien im eigenen Verzeichnis

Es würde Sinn machen, Ihr Ansichtsmodell Klassen haben. In meinen Projekten habe ich einen Unterordner der Model Ordner namens Viewmodel. Das ist, wo meine Viewmodel (z ProductViewModel.cs) leben.

Es gibt kein guter Ort, um Modelle zu halten. Sie sie in separate Baugruppe halten, wenn das Projekt groß und es gibt eine Menge von Viewmodels (Data Transfer Objects). Diese können Sie ebenfalls in separaten Ordner des Standorts Projekt halten. Zum Beispiel in Oxite sie in Oxite Projekt gestellt werden, die zu viele verschiedene Klassen enthält. Controller in Oxite wird getrenntes Projekt verschoben und Ansichten sind in separatem Projekt zu.
In CodeCampServer Viewmodels sind benannt * Form und sie sind in UI-Projekt in Models Ordner abgelegt.
In MvcPress Projekt werden sie in Daten-Projekt gelegt, die auch den gesamten Code enthält mit Datenbank und ein bisschen mehr arbeiten (aber ich habe diesen Ansatz nicht empfehlen, es ist nur für eine Probe)
So kann man es sehen viele Sicht sind. Ich halte in der Regel meine Viewmodels (DTO-Objekte) in der Website-Projekt. Aber wenn ich mehr als 10 Modelle habe ich es vorziehen, sie zu bewegen Montage zu trennen. Normalerweise in diesem Fall ich bin bewegt Controller Baugruppe zu trennen.
Eine andere Frage ist, wie man leicht alle Daten vom Modell Ihrem Ansichtsmodell abzubilden. Ich schlage vor, einen Blick auf AutoMapper Bibliothek zu haben. Ich mag es sehr viel, es tut alle schmutzige Arbeit für mich.
Und ich schlage ich vor, auch zu schauen SharpArchitecture Projekt. Es bietet eine sehr gute Architektur für Projekte und es enthält eine Menge cooler Frameworks und Anleitungen und großer Gemeinschaft.

hier ist ein Code-Schnipsel aus meiner bewährten Methode:

    public class UserController : Controller
    {
        private readonly IUserService userService;
        private readonly IBuilder<User, UserCreateInput> createBuilder;
        private readonly IBuilder<User, UserEditInput> editBuilder;

        public UserController(IUserService userService, IBuilder<User, UserCreateInput> createBuilder, IBuilder<User, UserEditInput> editBuilder)
        {
            this.userService = userService;
            this.editBuilder = editBuilder;
            this.createBuilder = createBuilder;
        }

        public ActionResult Index(int? page)
        {
            return View(userService.GetPage(page ?? 1, 5));
        }

        public ActionResult Create()
        {
            return View(createBuilder.BuildInput(new User()));
        }

        [HttpPost]
        public ActionResult Create(UserCreateInput input)
        {
            if (input.Roles == null) ModelState.AddModelError("roles", "selectati macar un rol");

            if (!ModelState.IsValid)
                return View(createBuilder.RebuildInput(input));

            userService.Create(createBuilder.BuilEntity(input));
            return RedirectToAction("Index");
        }

        public ActionResult Edit(long id)
        {
            return View(editBuilder.BuildInput(userService.GetFull(id)));
        }

        [HttpPost]
        public ActionResult Edit(UserEditInput input)
        {           
            if (!ModelState.IsValid)
                return View(editBuilder.RebuildInput(input));

            userService.Save(editBuilder.BuilEntity(input));
            return RedirectToAction("Index");
        }
}

Wir werfen alle unsere Viewmodels in den Models Ordner (alle unsere Business-Logik ist in einem separaten ServiceLayer Projekt)

Persönlich würde ich vorschlagen, wenn das Ansichtsmodell ist alles andere als trivial dann eine eigene Klasse verwenden.

Wenn Sie mehr als ein Ansichtsmodell haben, dann schlage ich es Sinn machen, es in mindestens einem Verzeichnis zu partitionieren. wenn das View-Modell dann später geteilt wird der Namensraum im Verzeichnis implizierte macht es leichter zu einer neuen Montage zu bewegen.

In unserem Fall haben wir die Modelle zusammen mit den Steuerungen in einem Projekt getrennt von den Ansichten.

Als Faustregel gilt: Wir haben versucht, den größten Teil der Bildschirmtextsystem zu bewegen und zu vermeiden [ „...“] Zeug zum Ansichtsmodell so vermeiden wir Guss- und Magie Saiten, was eine gute Sache ist.

Das Ansichtsmodell hält auch einige gemeinsame Eigenschaften wie Paginierung Informationen für Listen oder Header-Informationen der Seite Paniermehl und Titel zu zeichnen. In diesem Moment hält die Basisklasse zu viele Informationen meiner Meinung nach, und wir können es in drei Stücke teilen, das grundlegendste und notwendigen Informationen für die 99% der Seiten auf einer Basis View-Modell, und dann ein Modell für die Listen und Modell für die Formulare, die spezifischen Daten für diese Szenarien halten und erben von der Basis ein.

Schließlich haben wir ein View-Modell implementieren für jede Einheit mit den spezifischen Informationen zu befassen.

Code in der Steuerung:

    [HttpGet]
        public ActionResult EntryEdit(int? entryId)
        {
            ViewData["BodyClass"] = "page-entryEdit";
            EntryEditViewModel viewMode = new EntryEditViewModel(entryId);
            return View(viewMode);
        }

    [HttpPost]
    public ActionResult EntryEdit(Entry entry)
    {
        ViewData["BodyClass"] = "page-entryEdit";            

        #region save

        if (ModelState.IsValid)
        {
            if (EntryManager.Update(entry) == 1)
            {
                return RedirectToAction("EntryEditSuccess", "Dictionary");
            }
            else
            {
                return RedirectToAction("EntryEditFailed", "Dictionary");
            }
        }
        else
        {
            EntryEditViewModel viewModel = new EntryEditViewModel(entry);
            return View(viewModel);
        }

        #endregion
    }

Code in Ansicht Modell:

public class EntryEditViewModel
    {
        #region Private Variables for Properties

        private Entry _entry = new Entry();
        private StatusList _statusList = new StatusList();        

        #endregion

        #region Public Properties

        public Entry Entry
        {
            get { return _entry; }
            set { _entry = value; }
        }

        public StatusList StatusList
        {
            get { return _statusList; }
        }

        #endregion

        #region constructor(s)

        /// <summary>
        /// for Get action
        /// </summary>
        /// <param name="entryId"></param>
        public EntryEditViewModel(int? entryId)
        {
            this.Entry = EntryManager.GetDetail(entryId.Value);                 
        }

        /// <summary>
        /// for Post action
        /// </summary>
        /// <param name="entry"></param>
        public EntryEditViewModel(Entry entry)
        {
            this.Entry = entry;
        }

        #endregion       
    }

Projekte:

  • DevJet.Web (das ASP.NET MVC Web Projekt)

  • DevJet.Web.App.Dictionary (a seperate -Klassenbibliotheksprojekt)

    In diesem Projekt habe ich einige Ordner wie: DAL, BLL, BO, VM (Ordner für Ansicht Modelle)

Erstellen Sie eine Ansicht Modell Basisklasse, die üblicherweise Eigenschaften wie Ergebnis der Operation und Kontextdaten erforderlich ist, können Sie auch die aktuellen Benutzerdaten und Rollen setzen können

class ViewModelBase 
{
  public bool HasError {get;set;} 
  public string ErrorMessage {get;set;}
  public List<string> UserRoles{get;set;}
}

in der Basis-Controller Klasse haben eine Methode wie PopulateViewModelBase () Mit dieser Methode wird die Kontextdaten und Benutzerrollen aufzufüllen. Die HasError und Errormessage, stellen diese Eigenschaften, wenn es Ausnahme ist, wenn Daten von Service / db ziehen. Binden Sie diese Eigenschaften auf Sicht Fehler zu zeigen. Benutzerrollen können verwendet werden, auf Sicht zu zeigen, verstecken Abschnitt basierend auf Rollen.

Um Ansicht Modelle in verschiedenen bekommen Aktionen zu füllen, kann es durch mit Basis-Controller mit abstrakter Methode FillModel konsistent gemacht werden

class BaseController :BaseController 
{
   public PopulateViewModelBase(ViewModelBase model) 
{
   //fill up common data. 
}
abstract ViewModelBase FillModel();
}

In Controller

class MyController :Controller 
{

 public ActionResult Index() 
{
   return View(FillModel()); 
}

ViewModelBase FillModel() 
{ 
    ViewModelBase  model=;
    string currentAction = HttpContext.Current.Request.RequestContext.RouteData.Values["action"].ToString(); 
 try 
{ 
   switch(currentAction) 
{  
   case "Index": 
   model= GetCustomerData(); 
   break;
   // fill model logic for other actions 
}
}
catch(Exception ex) 
{
   model.HasError=true;
   model.ErrorMessage=ex.Message;
}
//fill common properties 
base.PopulateViewModelBase(model);
return model;
}
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top