Vanilla MVC4: Step 12 – HtmlHelpers

  • Neues Projekt: Klassenbibliothek Malt.MVC
  • Referenz hinzufügen: System.Web
  • MVC installieren: Install-Package Microsoft.AspNet.Mvc
  • Klasse entfernen: Class1
  • Neuer Ordner: Helper
  • Neue Klasse: public static HtmlHelperExtensions
  • Extension-Method: public static MvcHtmlString MenuListItem(this HtmlHelper htmlHelper

Im Projekt Malt.VanillaMVC.Web.UI

  • Referenz hinzufügen: Malt.MVC
  • Namespace in der ~/Views/Web.config hinzufügen: Malt.MVC.Helper
  • ul-ListItems ersetzen in der ~/Views/_RootLayout.cshtml

Vanilla MVC4: Step 11 – Routing I

Jetzt nun ein erster Post, der das Routing ein wenig auseinandernimmt. Zunächst in Bezug auf Areas. Um Links auf Controller korrekt zu bauen, ist ab sofort die Area notwendig.

In unserem Layout _RootLayout.cshtml passen wir also das Menu wie folgt an:

Den Brand-Link:

@Html.ActionLink("LeanBook", "Index", "Default", new { area="" }, new { @class="brand" })

Und die Navigation:

<ul class="nav" id="page-nav">
  <li class="active" data-mi="home">
    @Html.ActionLink("Home", "Index", "Default", new { area="" }, null)
  </li>
  <li data-mi="github">
    @Html.ActionLink("GitHub", "Index", "Home", new { area="GitHub" }, null)
  </li>
  <li data-mi="links"><a href="/#Links">Links</a></li>
  <li data-mi="todo"><a href="/#Todo">Todo</a></li>
  <li data-mi="about">
    @Html.ActionLink("Über", "About", "Default", new { area="" }, null)
  </li>
</ul>

Das Weglassen des Controllers funktioniert übrigens nicht. Es wird dann nicht der Default-Controller gewählt – sondern der aktuelle. Trotzdem lassen sich die erzeugten URLs kürzen, wenn wir in der GitHubAreaRegistration auch einen Default-Controller festlegen – nämlich den Home.

Immer noch sieht übrigens das globale Routing den HomeController der GitHub-Area (siehe http://localhost:1487/Home), aber umgedreht das Area-Routing nicht den DefaultController (siehe http://localhost:1487/GitHub/Default/).

Ein Blick auf das die Routen in Glimpse bringt uns der Lösung etwas näher:

Route DataTokens

Während die Area-Route DataTokens enthält wie Namespaces, area und UseNamespaceFallback sind die Tokens bei der globalen Route nicht vorhanden. Dabei weist Namespaces das Routing an, nur Controller aus diesem(n) Bereich(en) zu durchsuchen (ein String-Array), und UseNamespaceFallback erlaubt – wenn true – auch den Fallback auf alle anderen Namespaces. Wir müssen also beim globalen Routing ebenso die Namespaces festlegen und den Fallback unterbinden:

RouteTable.Routes.MapRoute(
    name: "Default",
    url: "{controller}/{action}",
    defaults: new { controller = "Default", action = "Index" },
    namespaces: new string[] { "Malt.Vanilla.Web.UI.Controllers" }
).DataTokens["UseNamespaceFallback"] = false;

Nun verhält sich das Routing ersteinmal konsistent. Zeit, um die beiden weiteren Areas Links und Todo anzulegen. Jeweils mit HomeController und Index-Action plus View. Nicht vergessen: jeweils _ViewStart.cshtml kopieren und (falls gewünscht) den Default-Controller in der AreaRegistration einzustellen sowie natürlich die Links im _RootLayout.cshtml anzupassen.

Übrigens wer jetzt die Namespaces-Einschränkungen wieder entfernt, erzeugt ein neues Problem beim Aufruf der (ohnehin unsinnigen) Url: http://localhost:1487/Home. Aber das gleiche Problem tritt natürlich auch dann auf, falls ein globaler Controller ebenso ein HomeController wäre …

No Namespace Routing

Fehler klar?!

Vanilla MVC4: Step 10 – Areas

In größeren Anwendungen nimmt die Anzahl der Controller, Models und Views starkt zu und damit auch eine gewisse Unübersichtlichkeit.

Mit MVC2 wurden die Areas eingeführt, um MVC-Anwendungen eine gewisse Modularität zu spendieren. Eine Area ist als Modul zu verstehen, dass in der Ordner-Struktur des Moduls wieder die globale Ordner-Struktur abbildet.

Eine Area wird ganz einfach hinzugefügt über: rechte Maustaste auf dem Projekt → Add/Hinzufügen…Area…

Unsere erste Area nennen wir GitHub. Angelegt wird die oben genannte Ordner-Struktur sowie eine eigene Web.config (Inhalt größtenteils nun bekannt) sowie eine Registrierungsklasse (Kindklasse von AreaRegistration) in der u.a. die Routen definiert werden.

mvc-area

Wir legen einen Controller an (HomeController) und mit einem Click auf die rechte Maustaste in der Action-Methode Index den dazugehörigen View (ohne festgelegtes layout). Außerdem kopiere ich deshalb schon mal die _ViewStart.cshtml.

Zunächst nun zu einem interessanten Fehler: Der Aufruf http://localhost:1487/Home/Index zeigt, dass der Controller schon gefunden(!) wird. In den globalen Views existiert aber natürlich kein View Home/Index. Wer sich die GitHubAreaRegistration-Klasse etwas näher angeschaut hat, entdeckt dort natürlich ein Route-Prefix /GitHub/. Damit dieses aber greift muss unsere Area aber tatsächlich registriert werden. Dies erledigt ein Aufruf einer statischen Methode der Basis-Klasse AreaRegistration zu Beginn der Application_Start-Methode in der Global.asax:

AreaRegistration.RegisterAllAreas();

Nun lässt sich der Area-Controller aufrufen über http://localhost:1487/GitHub/Home/Index.

Allerdings sind längst nicht alle Problem behoben (siehe About-Link auf der GitHub-Seite), doch dazu mehr im nächsten Posting.

Vanilla MVC4: Step 09 – Glimpse

In diesem Schritt werde ich mit glimpse eine Toolbar im Projekt / auf der Webseite hinzufügen, die mir einen umfassenden Einblick in die Server-Seite erlaubt.

Glimpse sammelt Daten über

  • Server Konfiguration
  • Request und Response Daten
  • Routing
  • Model Binding
  • Session
  • Timings

und vieles mehr (auch erweiterbar).

Die Installation über die Paketmanager-Console:

Install-Package Glimpse.Mvc4

Ich habe gleich die Mvc4-Variante gewählt, fürs erste hätte vielleicht auch die einfache ASP.NET-Variante gereicht (die durch Dependencies hinzugefügt wurde). Die Installation hat ein Modul registriert (Web.config – vielleicht neu formatieren) und eine Beispiel-Klasse zum Modifizieren der SecurityPolicies (wann wird die Glimpse-Debugtoolbar angezeigt?) bereitgestellt.

Wir rühren beides zunächst nicht an. Und schalten Glimpse einfach ein über den Aufruf der Seite http://localhost:1487/glimpse.axd.

Ab sofort befindet sich am unteren Rand unserer Web-Seite die Toolbar.

Vanilla MVC4: Step 08 – NuGet Package Restore

Bis hierher vergessen zu erwähnen habe ich, dass ich die NuGet Pakete nicht in git eingecheckt habe, um mein Repository schmaler zu halten. Es war also notwendig vor dem ersten Build alle NuGet-Pakete händisch einzeln zu installieren.

Seit NuGet 2.0 gibt es das Feature NuGet Package Restore. Damit richten wir die Solution so ein, dass bei einem Build-Vorgang fehlende Pakte nachinstalliert werden.

Zwei Schritte sind notwendig:

  1. In den VS-Optionen unter dem Punkt Package Manager (hab kein deutsches VS zur Hand – vielleicht Paketverwaltung?) den Haken bei Allow NuGet to download missing packages during build zu setzen.

  2. Auf der eigenen Solution rechte Maustaste → *Enable NuGet Package Restore**

Es wird damit ein Ordner .nuget auf Projektmappen-Ebene angelegt, der im Kern den Inhalt zweier NuGet-Pakete enthält: eine NuGet.exe sowie einen Build-Task, der von jedem Projekt der Mappe importiert wird. Den Ordner habe ich unter den Solution Items versteckt.

Zum Testen: packages-Ordner löschen und mit F6 Projektmappe erstellen lassen.

Details hierzu: NuGet docs