Owin showed up sometime in 2012. The first time I’ve heard about it was on an Hanselminutes episode about Kayak (a web server build in entirely using .net). It is already used in ASP.NET 4 and it will be heavily used in ASP.NET Core.
The idea behind Owin is to provide an abstraction that both web servers and frameworks can use. It boils down to two important concepts, the environment dictionary, and the application delegate.
The environment dictionary is a collection of key value pairs that describe a request and the response to that request. In .Net this is literally a IDictionary<string, object>
with keys such as owin.RequestBody
, owin.RequestHeaders
or owin.ResponseBody
.
The application delegate is a function that takes an environment dictionary and returns a Task
(Func<IDictionary<string, object>, Task>
).
Picture a web server that can take an http request, create an environment dictionary with the data from that http request, pass it on to an application delegate, wait for the delegate’s task to finish and finally, create a response using the data in the environment dictionary (that was updated by the application delegate) and send it.
If you think of the application delegate as ASP.NET MVC (assuming that the environment dictionary is converted to a Request
object, and the Response that MVC produces can be incorporated in the environment dictionary), it becomes clear that MVC could be used in any server that is capable of producing an environment dictionary. This also means that any web framework that can take an environment dictionary can be used in any server.
If you think about it, the environment dictionary is the minimum that is required to describe a request and a response to that request. The application delegate is the minimum that is required to specify a “handler” for that request.
Owin Middleware
Even though the definition of application delegate seems very simple, “it is just a function that takes a dictionary as a parameter and returns a Task
“, the way it is used in the Owin specification is nuanced.
At first glance the application delegate might seem like it abstracts a framework, such as ASP.NET MVC. In reality it represents the execution of several components that form a pipeline to “inspect, route, or modify request and response messages”. Under this perspective, ASP.NET MVC is just one of those components, and the application delegate represents executing them all.
Each of these components is called an Owin Middleware. In .Net’s implementation of Owin, named Katana, a middleware takes the form of a class that in it’s constructor has a parameter for the next middleware to call. This is how the pipeline is formed.
In Katana’s implementation of Owin the middleware runs in a particular order. Say, for example that you have three middlewares:
Middleware1
Middleware2
Middleware3
They will run in this order Middleware1, Middleware2, Middleware3, Middleware2, Middleware1.
This is easier to understand if we look at what is actually called when a middleware runs:
public async Task Invoke(IOwinContext context) {
//do some work
await Next.Invoke(); //this will be the rest of the pipeline running
//do some more work
}
(IOwinContext
is how the environment dictionary is accessed in Katana. Think of it as a friendlier version of the environment dictionary)
A real world example will make this even clearer. In an ASP.NET MVC5 project created with Individual User Accounts you can find, by looking in the Startup class (and other code that is called from there), these middlewares
being defined:
public void Configure(IAppBuilder app)
{
app.UseCookieAuthentication(...)
//...
//app.UseMvc();
}
(In Katana (the .Net implementation of Owin) this is how you build the pipeline: using the Startup class and IAppBuilder).
Every time a request comes through this pipeline it will first be handled by the cookie authentication middleware. The first thing that this middleware will do is check if the request contains a valid authentication cookie. If so, it creates an IPrincipal, that represents the user, using the data in the cookie, and then it invokes the next middleware. If not, it just invokes the next middleware.
The next middleware is ASP.NET MVC (it is “commented out” in the example because in this version of MVC this is done implicitly, however in MVC6 this is will be done explicitly).
If there was no cookie in the request (and therefore the user is not signed in) and the resource the user is trying to accept requires a signed in user, ASP.NET MVC will return a response with status code 401 Unauthorized. After this, the cookie middleware will run again, inspect the environment dictionary. It will be looking for a response code of 401, which it will find in this case. It will then change that response to 302 Redirect to the login page.
In very broad strokes this is how authorization works now. Previously this work was done by an HttpModule and an HttpHandler. The module was FormsAuthentication and the handler was MVC’s IHttpHandler implementation.
Owin/Katana and ASP.NET Core, MVC6 and MVC5
If you create an ASP.NET MVC6 project you’ll notice that it has a Startup.cs class, you’ll also notice that there isn’t a web.config. There are no http modules and handlers. This seems to be the way forward.
But don’t worry if you feel that you are still far away from using MVC6. You can use Owin/Katana today in you MVC5 projects. There’s a Nuget package that you can install in your MVC5 project, Microsoft.Owin.Host.SystemWeb
that will do the trick of converting requests to the environment dictionary (I had to ask how this works, it wasn’t/isn’t documented anywhere).
You then have to add a Startup class, there’s a visual studio template for that, just right click on the web project -> add -> owin startup class. You can now start using owin middlewares.
There’s a lot more to this, so I’ll leave you with some resources so that you can explore more about Owin and Katana:
http://odetocode.com/blogs/scott/archive/2013/07/09/getting-started-with-owin-katana-and-vs2013.aspx
http://odetocode.com/blogs/scott/archive/2013/11/11/writing-owin-middleware.aspx
http://odetocode.com/blogs/scott/archive/2013/11/12/simple-logging-middleware-katana-part-4.aspx
https://blogs.msdn.microsoft.com/webdev/2014/11/14/katana-asp-net-5-and-bridging-the-gap
http://www.asp.net/aspnet/overview/owin-and-katana/an-overview-of-project-katana
http://www.asp.net/aspnet/overview/owin-and-katana/owin-startup-class-detection