MVC LocationFormats

MVC LocationFormats

Habt ihr euch schon mal gefragt, wie MVC die Standard-Ordner, in denen nach Views gesucht wird, definiert?
Hierzu gibt es in MVC verschiedene View engines. Mein Ziel soll es in diesem Artikel sein, einen neuen Standard-Ordner für Partial views der Razor View engine hinzuzufügen.

Dazu möchte ich zuvor kurz erklären, wozu ich das überhaupt als Sinnvoll erachte.
Ich gehe davon aus, dass im Laufe der Entwicklung an einer MVC-Webseite, die Anzahl an partial views, sehr umfangreich werden könnte. Nun fände ich es sehr unübersichtlich, wenn alle partial views, master layouts usw. in einen einzigen Ordner liegen. Meine Idee war es nun, für bestimmte partial views, wie z.B. einer fürs paging, einen neuen Ordner Controls unter Shared zu definieren.

Folgendes müssen wir machen, um dies zu bewerkstelligen:
- Ermiteln der Razor view engine.
- Zu den aktuellen Standardpfaden, unseren neuen hinzufügen.

Dazu werde ich wie üblich in MVC, eine neue statische Konfigurations-Klasse für View engines erzeugen und diese in der global asax im Application_Start Event aufrufen.

Die folgende Klasse werde ich als globale Konfiguration für alle View engines verwenden. Hier werde ich im folgenden den neuen Ordner hinzufügen.
public class ViewEngineConfig
{
    public static void RegisterViewEngines(ICollection<IViewEngine> engines)
    {
           
    }
}
Wie ihr sehen könnt, handelt es sich dabei um eine einfache statische Klasse, die lediglich eine statische Methode beinhaltet. Diese Methode wird dann aus der global asax aufgerufen mit den aktuellen View engines als Parameter.

Somit fügen wir der global asax also folgenden Aufruf im Applicatation_Start Event hinzu:
public class Global : HttpApplication
{
    protected void Application_Start(object sender, EventArgs e)
    {
        ViewEngineConfig.RegisterViewEngines(ViewEngines.Engines);
    }
}

Als nächstes müssen wir uns die Razor View engine heraussuchen. Das ist notwendig, da standardmäßig auch weitere engines, wie z.B. die Webforms view engine, enthalten sind. Natürlich müsst ihr die jeweils für euch passende engine verwenden.

Ich erweitere die RegisterViewEngines Methode also um folgenden Code:
RazorViewEngine razorViewEngine = null;
foreach (IViewEngine engine in engines)
{
    if (engine.GetType() == typeof(RazorViewEngine))
    {
        razorViewEngine = (RazorViewEngine)engine;
        break;
    }
}
Ich iteriere also über alle verfügbaren engines und suche anhand des Typen nach der richtigen.

Sobald wir nun die richtige View engine zur verfügung haben, können wir auf folgende relevante Eigenschaften zugreifen:
- MasterLocationFormats
- ViewLocationFormats
- PartialViewLocationFormats
- AreaMasterLocationFormats
- AreaViewLocationFormats
- AreaPartialViewLocationFormats



Die hier aufgelisteten Eigenschaften geben die Standardordner, für alle Views an. Für mich ist also die Eigenschaft PartialViewLocationFormats wichtig.

Da ich die vorhandenen Ordner nicht ändern, sondern lediglich einen neuen hinzufügen möchte, füge ich also folgenden Code hinzu:
if (razorViewEngine != null)
{
    string[] additionalPartialViewLocations = new string[] 
    {
        "~/Views/Shared/Controls/{0}.cshtml"
    };

    razorViewEngine.AreaPartialViewLocationFormats = razorViewEngine.PartialViewLocationFormats
        .Union(additionalPartialViewLocations).ToArray();
}
Ich erstelle ein neues Array, mit meinem neuen Pfad. Danach füge ich dieses Array, dem vorhanden über Union hinzu. Bitte beachtet, dass der Platzhalter {0} hier für den Dateiname steht. Dieser wird später zur Laufzeit von MVC automatisch ersetzt.



Ab sofort kann ich nun also auch partial views, diesem Ordener hinzufügen.
Das ermöglicht mir eine globale partial view zu erstellen, die ich fürs paging wie folgt in meinen views verwenden kann:
@Html.Partial("_Paging", new PagingModel(Model.TotalPages, 10, Model.Page))
Um einen Kommentar zu hinterlassen, ist eine Anmeldung erforderlich.