Thomas Bandt

Über mich | Kontakt | Archiv

ASP.NET MVC 3 - eigene Basisklasse für Razor-Views

Ich habe es mir angewöhnt bestimmte in den Views immer wiederkehrende Sachen in entsprechende Basisklassen zu packen, über die ich dann einen einfache und typisierten Zugriff darauf bekomme - als Beispiel wäre der angemeldete Benutzer zu nennen. In MVC 2 sieht das dann so aus:

   1:  public class AppViewPage<TModel> : ViewPage<TModel>
   2:  {
   3:      private User currentUser;
   4:      public User CurrentUser
   5:      {
   6:          get { return currentUser ?? (currentUser = new User()); }
   7:      }
   8:  }

Anwendung:

   1:  <%@ Page Language="C#" Inherits="AppViewPage<ViewModel.MessageViewModel>" %>
   2:   
   3:  <% if(CurrentUser.Account.NotificationsEnabled) { %>
   4:   ... mach was
   5:  <% } %>

Nun ist in Razor ja die Deklaration der Basisklasse aus den Views verschwunden ... na ja, nicht ganz. Die globale Konfiguration steckt nun in der Web.config für den Views-Ordner (jeweils auch in jeder Area). Das Prinzip ist das Gleiche, der Typ für die Basisklasse, von dem abgeleitet werden muss, ist ein anderer. Die Razor-Variante des obigen Beispiels sieht dann so aus:

   1:  public abstract class AppViewPage<TModel> : System.Web.Mvc.WebViewPage<TModel>
   2:  {
   3:      private User currentUser;
   4:      public User CurrentUser
   5:      {
   6:          get { return currentUser ?? (currentUser = new User()); }
   7:      }
   8:  }

Wichtig ist, dass die Klasse abstract ist, da sonst die Execute-Methode von Hand implementiert werden muss - was an dieser Stelle absolut unnötig ist.

Die Registrierung (unter /Views/Web.config und ggf. /{Area}/Views/Web.config):

   1:  <system.web.webPages.razor>
   2:    <host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
   3:    <pages pageBaseType="Blubr.App.ViewModel.AppViewPage">
   4:      <namespaces>
   5:        <add namespace="System.Web.Mvc" />
   6:        <add namespace="System.Web.Mvc.Ajax" />
   7:        <add namespace="System.Web.Mvc.Html" />
   8:        <add namespace="System.Web.Routing" />
   9:        <add namespace="Blubr.App.ViewModel" />
  10:      </namespaces>
  11:    </pages>
  12:  </system.web.webPages.razor>

Und die Verwendung in der View:

   1:  @if(CurrentUser.Account.NotificationsEnabled) {
   2:      mach was ...
   3:  }

Unterm Strich ein bisschen DRY - man spart sich halt die ständig wiederkehrende Deklaration in jeder View und kann die Klasse bei Bedarf auch einfacher austauschen. Nicht so schick gelöst finde ich, dass die Definition in jeder Web.config vorgenommen werden muss - ich habe im Moment 5 Areas + den globalen Views-Ordner, macht also 6 Stellen, an denen diese Einstellung zu pflegen ist.

Kommentare

  1. Lennart schrieb am Montag, 20. Dezember 2010 17:05:00 Uhr:

    Hallo Thomas,

    kannst du den "system.web.webPages.razor"-Bereich nicht in die Web.config vom Stammverzeichnis verschieben? Das müsste dann doch für alle Razor-Views im Projekt gelten und die anderen Web.Config-Dateien wären überflüssig, oder gibt das unerwünschte Nebeneffekte?
  2. Albert Weinert schrieb am Montag, 20. Dezember 2010 23:23:00 Uhr:

    Jupp, wäre möglich.

    Eine Web.config in der Areas reicht auch und eine Views würde auch gehen, ist eine Hierarchie.

    Nebeneffekte wären das .cshtml Dateien die da rumliegen angezeigt werden würden.
  3. Lennart schrieb am Dienstag, 21. Dezember 2010 10:21:00 Uhr:

    ja stimmt, aber dafür kann man den BlockViewHandler ja auch noch übernehmen und mit dem path-Attribut das Blocken auf cshtml-Dateien beschränken: path="*.cshtml"


« Zurück  |  Weiter »