CHAPTER 8
The Open Web Interface for .NET (OWIN) is a Microsoft specification that defines a contract for .NET applications to interact with web servers. This includes the pipeline for execution of HTTP requests and contracts for services to sit in between (middleware). It also happens to be the basis for the upcoming ASP.NET 5.
OWIN allows you to decouple your service application from any particular web server, such as IIS. Although it can use IIS, it can also be self-hosted (like WCF) through OWIN’s web server implementation, OwinHttpListener.
You will need to add a reference to the Microsoft.Owin.Host.HttpListener NuGet package:
![]()
Why should we care with OWIN? Well, for once, it gives you a consistent pipeline that is more aligned with the way ASP.NET will be in the near future: no more Web Forms—MVC will be configured through OWIN!
Note: For a good introduction to OWIN, check out the book OWIN Succinctly, by Ugo Lattanzi and Simone Chiaretta, also in the Succinctly collection.
The OWIN pipeline starts with a call to a method called Configuration of a class called Startup. This is by convention; there is no base class or interface that dictates this, and both the class and method can even be static. If we want to change this bootstrap method, we can do so by adding an OwinStartupAttribute at the assembly level or a “owin:appStartup” entry to the Web.config’s appSettings section. Here we register a middleware component that in return, will register all our services (like tenant identification and registration):
Code Sample 82
public static class Startup { public static void Configuration(IAppBuilder builder) { builder.UseStaticFiles(); builder.UseDefaultFiles(); //rest goes here builder.Use<MultitenancyMiddleware>(); //rest goes here } } |
The middleware class inherits from OwinMiddleware—there are other options, but this is my favorite one. A middleware class receives in its constructor a pointer to the next middleware in the pipeline, and should return the result of its invocation in its Invoke method.
An example:
Code Sample 83
public class MultitenancyMiddleware : OwinMiddleware { public MultitenancyMiddleware(OwinMiddleware next) : base(next) { }
public override Task Invoke(IOwinContext context) { //services registration context.Set<ITenantLocationStrategy>( typeof(ITenantLocationStrategy).FullName, new MefTenantLocationStrategy( typeof(Common.ContextRepository).Assembly)); context.Set<ITenantIdentifierStrategy>( typeof(ITenantIdentifierStrategy).FullName, new HostHeaderTenantIdentifierStrategy()); context.Set<IConfiguration>( typeof(IConfiguration).FullName, new AppSettingsConfiguration()); //rest goes here return this.Next.Invoke(context); } } |
Note: Right now, you cannot use OWIN with ASP.NET MVC or Web Forms, because these depend on the System.Web.DLL, the core of the ASP.NET framework, but ASP.NET MVC 6 will work on top of OWIN.
So, if you are to use OWIN, and you need to resolve one of our bootstrap services, you can either stick with your choice of IoC container and Common Service Locator, or you can use OWIN’s internal implementation:
Code Sample 84
public override Task Invoke(IOwinContext context) { var tls = context.Get<ITenantLocationStrategy>( typeof(ITenantLocationStrategy).FullName); return this.Next.Invoke(context); } |
OWIN also supports ASP.NET Identity for authentication. Just add NuGet package Microsoft.AspNet.Identity.Owin and make any changes to the added classes:
![]()
Unlike MVC, Web API can be used with OWIN. You will need to register an implementation, such as the one provided by the Microsoft NuGet package Microsoft.AspNet.WebApi.Owin:
![]()
Then you will need to register the Web API service in the aforementioned Configuration method, using the UseWebApi extension method:
Code Sample 85
public static class Startup { public static void Configuration(IAppBuilder builder) { builder.UseWebApi(new HttpConfiguration()); //rest goes here } } |
OWIN came into being because of the desire to replace the System.Web architecture. One key class in System.Web is HttpContext, which no longer exists in OWIN. This poses a problem: our interfaces that were introduced earlier, namely ITenantIdentifierStrategy, rely on classes that are part of System.Web, so we need to figure out how we can achieve the same results without it. The OWIN pipeline is significantly simpler than ASP.NET; it follows a pattern known as Chain of Responsibility, where each stage (called middleware) in the pipeline calls the next one, eventually doing something before and after that. So, if we want to make available some services to the other, we need to do it in the first stage:
Code Sample 86
public class OwinHostHeaderTenantIdentifierStrategy : OwinMiddleware { public OwinHostHeaderTenantIdentifierStrategy(OwinMiddleware next): base(next) { }
public override Task Invoke(IOwinContext context) { context.Request.Environment["Tenant"] = TenantsConfiguration.GetTenants().Single(x => x.Name == context.Request.Host.Value.Split(':') .First().ToLower());
return this.Next.Invoke(context); } } |
The equivalent of the HttpContext in OWIN is the implementation of the IOwinContext interface: it has Request and Response objects, plus a couple of other useful methods and properties. In this example, we are storing the current tenant, as identified by the host header, in an environment variable (the Environment collection). OWIN does not dictate how to do it, so please feel free to do it any way you prefer. The important thing is that this middleware needs to be inserted on the pipeline before anything else that might need it:
Code Sample 87
public static class Startup { public static void Configuration(IAppBuilder builder) { builder.UseWebApi(new HttpConfiguration()); builder.UseStaticFiles(); builder.UseDefaultFiles(); //rest goes here builder.Use<MultitenancyMiddleware>(); builder.Use<OwinHostHeaderTenantIdentifierStrategy>(); //rest goes here } } |
In order to unit test an OWIN setup, we may need to inject a couple of properties, such as the current host, so that it can be caught by our implementation of the Host header strategy:
Code Sample 88
public static void Setup(this IOwinContext context) { context.Request.Host = new HostString("abc.com"); } |
Other strategies don’t need any particular setup.