26 September 2013 OWIN, Razor, WebApi Robert Muehsig

Die ersten Schritte mit OWIN sind recht schnell gemacht. In diesem Blogpost möchte ich über OWIN die WebAPI nutzen – allerdings nicht als REST Endpunkt, sondern um HTML zurückzugeben. Für alle die mit OWIN garnichts anfangen können, der könnte ein Blick auf meine Unterlagen werfen.

Warum nicht ASP.NET MVC?

Aktuell ist das MVC Framework sehr an das ursprüngliche ASP.NET Framework gebunden – das bereits über 10 Jahre alte Framework war auf das Hosting im IIS ausgelegt. Wer heute also eine Webapplikation baut, welche evtl. auf verschiedenen Hosts (“Selfhosting”, andere OWIN-Hosts – also nicht IIS Hosts) laufen soll, für den kann MVC in eine Sackgasse enden.

Ist die WebApi nicht nur für REST Services da?

Grundsätzlich verbinden viele die WebAPI mit Json oder Xml ausgaben – jedoch ist das größte Medium im Netz “HTML” und natürlich kann die WebApi auch dies zurückgeben.

Code

Damit die WebApi mit Razor umgehen kann nutze ich das WebApiContrib Package. Dies kommt alles in die Owin Config rein. Wenn ein Controller über das Routing gefunden wird schlägt die WebApi zu, andernfalls wird die Owin “WelcomePage” ausgegeben.

   1: [assembly: OwinStartup(typeof(RazorWebApiOwin.Startup))]
   2: namespace RazorWebApiOwin
   3: {
   4:     public class Startup
   5:     {
   6:         public void Configuration(IAppBuilder app)
   7:         {
   8:             GlobalConfiguration.Configuration.Formatters.Add(new HtmlMediaTypeViewFormatter());
   9:  
  10:             GlobalViews.DefaultViewParser = new RazorViewParser();
  11:             GlobalViews.DefaultViewLocator = new RazorViewLocator();
  12:  
  13:             var config = new HttpConfiguration();
  14:             config.Routes.MapHttpRoute("default", "{controller}");
  15:             config.Formatters.Add(new HtmlMediaTypeViewFormatter());
  16:  
  17:             app.UseWebApi(config);
  18:  
  19:             app.UseWelcomePage();
  20:         }
  21:     }
  22: }

 

Der Controller samt dem “Model” sieht so aus:

   1: // http://weblogs.asp.net/fredriknormen/archive/2012/07/17/asp-net-web-api-and-using-razor-the-next-step.aspx
   2:     public class HomeController : ApiController
   3:     {
   4:         public Value GetValues()
   5:         {
   6:             // Option via return type: return new View("Home", null);
   7:             return new Value() { Numbers = new int[] { 1, 2, 3 } };
   8:         }
   9:     }
  10:  
  11:     [View("Home")]
  12:     public class Value
  13:     {
  14:         public int[] Numbers { get; set; }
  15:     }

Das Attribut “View” kommt von dem WebApi Contrib Package.

Der View:

   1:  
   2: <html>
   3: <head>
   4:     <title>Hello World!</title>
   5: </head>
   6: <body>
   7:     <h1>Hello World!</h1>
   8:     <ul>
   9:         @foreach (var value in Model.Numbers)
  10:         {
  11:             <li>@value</li>
  12:         }
  13:     </ul>
  14: </body>
  15: </html>

“Normaler” Razor Code – allerdings scheint der @model Syntax eine MVC spezifische Erweiterung zu sein. Damit geht leider die Intellisense verloren, aber evtl. gibt es einen Weg.

Testen

Das Projekt lässt sich über das OwinHost Package auch über die Konsolenapplikation starten.

image

Die “WelcomePage”:

image

Greife ich nun auf localhost:12345/Home über einen Browser zu wird mir der View zurückgegeben.

image

Falls ich aber ein JSON anfordere (oder besser gesagt kein HTML) bekomme ich das JSON zurück:

image

Hypermedia. Yay.

Fazit

Die WebApi ist auch ohne OWIN einen Blick wert, wer sich aber doch intensiver mit OWIN beschäftigen möchte, der sollte sich nach Alternativen für MVC umsehen. Die WebApi ist hierbei sehr hilfreich.

Der Code ist wie immer auch auf GitHub zu finden.


Written by Robert Muehsig

Software Developer - from Dresden, Germany, now living & working in Switzerland. Microsoft MVP & Web Geek.
Other Projects: KnowYourStack.com | ExpensiveMeeting | EinKofferVollerReisen.de

If you like the content and want to support me you could buy me a beer or a coffee via Litecoin or Bitcoin - thanks for reading!