Introduction
Hello everyone, in this series I will be writing out several different features of ASP.NET MVC5. I will be assuming you do have some knowledge of the previous versions of ASP.NET MVC or atleast knowledge of the MVC design pattern and .NET/C#. If not, I would suggest going through some basic ASP.NET MVC tutorials which would help you understand this article better.
To begin with let me give you a glimpse of what features does ASP.NET MVC5 have. The following mentioned technologies doesn't really mean that it comes with ASP.NET MVC5 but it more means that these are packaged up together with ASP.NET MVC5 thereby encouraging use of these. E.g. Bootstrap is a open source CSS/JS library for response design.
Bootstrap for responsive design
WebAPI 2 for creating RESTful services
EF6 for data access
OWIN/Katana – An entirely new middleware component
SignalR – Websocket communication and some more too
In this article I will try to explain and demonstrate OWIN/Katana as a middleware web framework.
Lets get started
Katana is a web framework which implements OWIN (Open Web Interface for .NET).
OWIN is a specification which defines standards for frameworks and servers to communicate.
OWIN defines a standard interface between .NET web servers and web applications. The goal of the OWIN interface is to decouple server and application, encourage the development of simple modules for .NET web development, and, by being an open standard, stimulate the open source ecosystem of .NET web development tools.
[Definition taken from http://owin.org/ ]
Katana is Microsoft’s implementation of OWIN specification.
To give you a heads up, you can try comparing it with the concept of Http Modules in the ASP.NET pipeline, which it actually uses under the hood. Beware that it’s just an analogy to help you make a beginning with but in reality it’s much more than that.
Assembly references to OWIN in a sample MVC5 application.
Let us go through the classic Hello World sample of OWIN/Katana.
- Create a console application using Visual Studio.
2. Install the following Nuget packages.
After installation of these 2 nuget packages, this is how your references should look like.
The HTTP listener nugget package is needed to listen on a specific port for HTTP requests.
3. Let’s also create a class library project to keep the Katana hosting code separately for decoupling and reuse. Make sure to install the same 2 nuget packages in this library project too.
4. Now let’s write the following pieces of code.
Class library Hosting class -->
using Owin;
namespace KatanaHosting
{
public class Hosting
{
public void StartHost(IAppBuilder appBuilder)
{
appBuilder.Run(
r => {
return r.Response.WriteAsync("Hello World Owin Katana!");
});
}
}
}
Console application Program.cs
using KatanaHosting;
using Microsoft.Owin.Hosting;
using System;
using System.Configuration;
namespace OwinHTTPServer
{
class Program
{
static void Main(string[] args)
{
string url = ConfigurationManager.AppSettings["url"].ToString();
{
Console.WriteLine("Host Started!");
Console.ReadLine();
Console.WriteLine("Host Stopped!");
}
}
}
}
5. Now let’s try running the console application. Chances are you will get the following exception if you followed the same code as mine above.
Looking at the detailed error message, we see the following.
The following errors occurred while attempting to load the app.
- No 'Configuration' method was found in class 'KatanaHosting.Hosting, KatanaHosting, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.
Yes, you are guessing right, if you are really guessing J.
We need to name the Hosting class method as Configuration(IAppBuilder appBuilder). Yes ASP.NET MVC has a lot of convention these days.
6. Now let’s try running the console app again and our Web Server is up and running.
7. Let’s test our Katana Web Server by spawning up a browser window and typing the url we gave in our configuration file, in my case http://localhost:9001 and voila here we have the web server response in our browser.
Microsoft.Owin.Diagnostics
Now let’s try exploring some features of OWIN/Katana.
Install another nugget package to our Hosting class library Microsoft.Owin.Diagnostics.
Now let’s change the Configuration method of our Hosting class to display a Welcome page instead of a Hello World response.
public class Hosting
{
public void Configuration(IAppBuilder appBuilder)
{
appBuilder.UseWelcomePage();
}
}
Now when we try browing http://localhost:9001, we see a beautiful welcome page.
AppFunc – The Application Function
The AppFunc function specifies how components interact with each other and does the HTTP Request processing.
AppFunc takes a delegate signature Func<IDictionary<string, object>, Task> which means it takes a dictionary and returns a task. The dictionary consists of mainly everything like the Request to the Server and the Response from the server. We can compare the dictionary with the HttpContext object in ASP.NET which contains the HTTP request processing details. The Func returns a task because we are talking asynchronous Request/Response here similar to Async/Await in MVC4. So it’s a non-blocking request/response system where one request doesn’t have to wait for the previous request to complete.
Don’t worry about the details here, we’ll see a sample soon.
Lets’ re-write our Welcome page sample above with some custom code that uses the Uses<> function to call our piece of code and returns a hello world string.
We write a new class here named “AppFuncServer”.
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
namespace KatanaHosting
{
public class AppFuncServer
{
Func<IDictionary<string, object>, Task>_next;
public AppFuncServer(Func<IDictionary<string, object>, Task> next)
{
_next = next;
} public async Task<string> Invoke(IDictionary<string, object> env)
{
await _next(env);
var response = env["owin.ResponseBody"] as Stream;
using(var writer = new StreamWriter(response))
{
return writer.WriteAsync("Hello World").ToString();
}
}
}
}
Hosting class
namespace KatanaHosting
{
public class Hosting
{
public void Configuration(IAppBuilder appBuilder)
{
appBuilder.Use<AppFuncServer>();
}
}
}
Run a browser window with http://localhost:9001/ and you will be able to see the Hello World again with new custom code.
Katana/OWIN as middleware
Did I tell you that OWIN is actually a middleware. Why?
Because it sits in the middle of the request pipeline and has capability to forward request to the next component. Let’s see how it acts as a middleware by trying to write the host header value in the server console app before the response.
Extending the sample above to output the host header value in the console app. Now do you believe it works as a middleware ;)
Hosting.cs class
using Owin;
using System; namespace KatanaHosting
{
public class Hosting
{
public void Configuration(IAppBuilder appBuilder)
{
appBuilder.Use(async (env, next) => {
Console.WriteLine(env.Request.Host.Value);
await next();
}); appBuilder.Use<AppFuncServer>();
}
}
}
You must be thinking OWIN and Katana hello world samples are fine, but where is my application that will ultimately be responsible for managing the business logic/rules/data access etc. Yes so you don’t have to wait anymore. Let’s walkthrough a sample of using a WebAPI which would also be self hosted.
WebAPI
- Install Microsoft.AspNet.WebApi.OwinSelfHost nugget package in the console application. This has some dependant packages which would be automatically installed.
- Let’s add a class file RouteConfig.cs. Yes I am trying to use the same pattern as ASP.NET WebAPI.
namespace KatanaHosting
{
public class RouteConfig
{
public static void RegisterRoutes(IAppBuilder appBuilder, ref HttpConfiguration config)
{
config.Routes.MapHttpRoute(
"DefaultApi",
"api/{controller}/{id}",
new { id = RouteParameter.Optional}
);
}
}
}
namespace KatanaHosting
{
public class Hosting
{
public void Configuration(IAppBuilder appBuilder)
{
Console.WriteLine(env.Request.Host.Value);
await next();
}); var config = new HttpConfiguration();
RouteConfig.RegisterRoutes(appBuilder, ref config);
appBuilder.UseWebApi(config);
appBuilder.Use<AppFuncServer>(); }
}
}
3. Add a HomeController class which inherits from ApiController to make it a WebAPI controller and add a simple Get method that returns a string.
namespace KatanaHosting
{
public class HomeController : ApiController
{
public string GetHome()
{
return "Hello World from Web API";
}
}
}
And that’s it to it. Run the console app to start the server and browse http://localhost:9001/api/Home and we would see webapi happily returning XML response back to client.
Katana and IIS
1. Install Nuget package into our library KatanaHosting.
This package is going to do the needful to hook up between the Katana and IIS pipeline and host the Katana middleware. It basically does this using its own HttpModules and HttpHandlers.
2. Change the output path of the KatanaHosting library project to bin directory because now we are trying to host this project under IIS.
3. Create a Web.config file for our KatanaHosting project as we need to host under IIS now.
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<appSettings>
<add key="owin:appStartup" value="KatanaHosting.Hosting" />
</appSettings>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.1.0.0" newVersion="2.1.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
4. Create a WebSite under IIS and point the physical directory to the KatanaHosting project.
5. Try browsing the site on the hosted port http://localhost:8080 and also the api url http://localhost:8080/api/Home and you should be able to browse the Hello World samples as previously but now hosted within IIS. BTW, to test the Katana middleware component which was previously writing the Request Host header value to the console, you can just try writing it out to a file.
Now let’s try to see the default ASP.NET MVC5 application using Katana/OWIN.
- Let’s create a new ASP.NET MVC5 application in Visual Studio 2013 or Visual Studio 2012(with http://www.microsoft.com/en-us/download/details.aspx?id=41532 ).
- If you open up the references, you can see the OWIN dll’s already present.
- You can also see a startup file in the root of the website with the following code.
using Microsoft.Owin;
using Owin;
[assembly: OwinStartupAttribute(typeof(Sample_MVC5.Startup))]
namespace Sample_MVC5
{
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
ConfigureAuth(app);
}
}
}
If you have a look at the ConfigureAuth() method, authentication stuffs are done there.
Also the assembly attribute above the namespace defines the startup class which in our KatanaHosting class library example we were doing in the Web.config so this is another way to configure the startup class.
Points of Interest
In this article, we learnt about how Katana using OWIN specification can be used as a middleware web framework and how it can be used in different kinds of applications like we used once in a console app and once in a website.
In future articles, we will look into more uses of Katana/OWIN and also other features of ASP.NET MVC5.