-
Notifications
You must be signed in to change notification settings - Fork 1
OWIN
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:
The Owin.dll assembly is distributed as a NuGet package and 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:
Host (IIS, Tomcat, etc)
| ^
| |
Request Response
| |
| |
OWIN
| |
V |
Application
OWIN sits between the hosting software and your application so that your application can run on any host without modification.
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 developer to write 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 a Use extension to the IAppBuilder interface that returns IAppBuilder.
The world view of Microsoft OWIN (Katana) can be depicted like this:
Host (IIS, Tomcat, etc)
| ^
| |
Request Response
| |
| |
OWIN
| |
| |
Middleware
| |
| |
Middleware
| |
V |
Application
Katana adds a pipeline of middleware that can examine the request and response and modify them. The middleware can also choose to not call the next middleware and produce the response itself.
The OwinFramework.dll package is layered on top the Microsoft OWIN package 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> 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 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.
The code that the application developer writes to configure the OWIN pipeline 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);
}