Conceptual Overview of The Owin Framework

Conceptual Overview

OWIN provides a set of standards for writing web applications that allow code from different authors to work together. These standards have the following layers:

OWIN

The Owin.dll assembly was writtin by Microsoft and is distributed as a NuGet package. It defines an interface between the web server and the web application. This allows any web hosting implementation to work with any application, so that you can host your web application on IIS, Apache, as a stand-alone Windows Service or even in a console application. This also means that framework builders can target OWIN and the consumers of the framework can choose any hosting platform which gives the framework far greater reach.

The OWIN assembly defines one interface called IAppBuilder that looks like this:

public interface IAppBuilder
{
   IDictionary<string, object> Properties { get; }
   object Build(Type returnType);
   IAppBuilder New();
   IAppBuilder Use(object middleware, params object[] args);
}

The world view of OWIN can be depicted like this:

OWIN world view

OWIN sits between the hosting software and your application so that your application can run on any host without modification.

Microsoft OWIN

The Microsoft.Owin.dll assembly is layered on top of Owin.dll. It wraps IAppBuilder.Properties in IOwinContext and defines the application as having a pipeline of middleware components chained through Func<Task> references.

The Microsoft OWIN package also contains an AppBuilder class which is a concrete implementation of IAppBuilder and defines a set of Use extension methods for IAppBuilder that add middleware into a chain.

When writing middleware components using the Microsoft OWIN assembly the standard implementation pattern is to write a class with a public Build method and private Invoke method like this:

public class MyMiddleware
{
   public void Build(IAppBuilder app)
   {
      app.Use(Invoke);
   }
   private Task Invoke(IOwinContext context, Func<Task> next)
   {
      return next();
   }
}

The middleware developer should also provide a Use extension for IAppBuilder that adds their middleware into the pipeline. This extension method typically looks like this:

public static IAppBuilder Use(this IAppBuilder appBuilder, MyMiddleware myMiddleware)
{
   myMiddleware.Build(appBuilder);
   return appBuilder;
}

This allows the application dveloper to construct a middleware pipeline using code like this:

public void Configuration(IAppBuilder app)
{
   app.Use(new Middleware1())
      .Use(new Middleware2())
      .Use(new Middleware3())
      .Use(new Middleware4());
}

This works because each middleware defines an extension method on the IAppBuilder interface called Use that returns the IAppBuilder instance.

The world view of Microsoft OWIN (Katana) can be depicted like this:

Katana world view

Katana extends the base OWIN concept by defining the application as a pipeline of middleware components where each middleware can choose to process the incomming http request or not, can choose to process the outgoing http reply or not, and can pass the request to the next middleware in the chain or not.

Owin Framework

The OwinFramework.dll assembly is layered on top the Microsoft.Owin.dll assembly by adding standardization for common middleware functionality like identification, authorization, session etc. This standardization provides the following benefits:

  • Application developers can seamlessly swap out any implementation of a particular type of middleware for any other implementation without breaking their OWIN pipeline.
  • Middleware developers can focus on doing a really good implementation of one piece of middleware and assume that other contributors will provide the other pieces needed to build a complete application.

This OWIN Framework also provides a routing mechanism, middleware dependency resolution and a flexible standardized way of configuring middleware components.

To take an existing middleware and make it work with the OWIN Framework the middleware developer needs to implement IMiddleware<T> where T defines if this is identification, authorization, session or whatever middleware. For generic middleware or application specific middleware T can be object.

A minimal implementation of IMiddleware<T> that can be chained into the pipeline but does nothing, looks like this:

public class MyMiddleware: IMiddleware<object>
{
   public string Name { get; set; }
   private readonly IList<IDependency> _dependencies = new List<IDependency>();
   public IList<IDependency> Dependencies { get { return _dependencies; } }
   public Task Invoke(IOwinContext context, Func<Task> next)
   {
      return next();
   }
}

Notice that to change existing middleware to be compatible with the OWIN Framework all we have to do is add a couple of properties and make the existing Invoke method public. These changes allow middleware to be named and have dependencies on other middleware. For example an implementation of identification might have a dependency on session.

If you want to use existing middleware that does not support the OWIN Framework and you don't have source code then there is a LegacyMiddlewareWrapper class that will allow you to use it with the OWIN Framework.

If you are starting from scratch, you can copy the code above and use it as a starting point for any new middleware that you write.

When using the Owin Framework, the code that the application developer writes to configure the pipeline of middleware changes to a fluent syntax like this:

public void Configuration(IAppBuilder app)
{
   var builder = new Builder();
   builder.Register(new NotFoundError())
      .As("staticFilesNotFoundError")
      .RunAfter("loginId")
      .ConfigureWith(configuration, "/owin/notFound/staticFiles");
   builder.Register(new FormsIdentification())
      .As("loginId")
      .ConfigureWith(configuration, "/owin/auth/forms")
      .RunOnRoute("secure");
   app.Use(builder);
}

Note that the Builder class from the example above is middleware from the Katana world view perspective, and it contains its own mechanism for chaining middleware. One of the reasons why the Owin Framework does this is because it support dependency resolution between middleware, allows multiple routes to be configured, and has an upstram and downstream method for middleware to communicate about the request processing.

The world view of this Owin Framework can be depicted like this:

Owin Framework world view