Getting started with OWIN

Owin is an Open Web Interface for .NET, it describes how components in a HTTP pipeline should communicate, like NodeJS Connect or Rack.

Owin has one main interface, every components will communicate through this interface.

Func<IDictionary<string, object>,Task>

//Actual implementation
public Task Invoke(IDictionary<string, object> environment) 
{ 
   var someObject = environment[some.key] as SomeObject; 
   // etc… 
}

Owin specs contains details of IDictionary object.

Owin host will composes multiple middlewares into a application. It will implement the following interface

public interface IAppBuilder 
{ 
    IDictionary<string, object> Properties { get; }

    object Build(Type returnType); 
    IAppBuilder New(); 
    IAppBuilder Use(object middleware, params object[] args); 
}

We compose middlewares in Configuration method of Startup class. When OwinHost starts, it looks into Configuration method to build up middlewares of our app.

public class Startup
{
  public void Configuration(IAppBuilder builder)
  {
      builder.Use(typeof(Logger));      
  }
}

Let build a simple logger and a request handler middleware

  • Create new blank MVC4 (or MVC5) project OwinTest
  • Add the following packages:

    Install-Package Owin
    Install-Package Install-Package Microsoft.Owin.Host.HttpListener -Pre

  • Create a new class Logger and enter the following code

using System.Collections.Generic;
using System.Threading.Tasks;
using AppFunc = System.Func<System.Collections.Generic.IDictionary<string, object>, System.Threading.Tasks.Task>;

public class Logger
{
    private readonly AppFunc _next;
    public Logger(AppFunc next)
    {
        if(next == null)
        {
          throw new ArgumentNullException("next");
        }
        _next = next;
    }
    public Task Invoke(IDictionary<string, object> environment)
    {
        System.Diagnostics.Trace.WriteLine(string.Format("{0} {1}",DateTime.Now, environment["owin.RequestPath"]));
        return _next(environment);
    }
}
  • Create a class Startup and enter the following code
public class Startup
{
  public void Configuration(IAppBuilder builder)
  {
      builder.Use(typeof(Logger));      
  }
}
  • Download Katana hosting, extract to C:\ (or any folder)
  • Open Project property, confiure Start external program
    Project property
  • Press F5 and browse http://localhost:8080 the console will show like this console result

  • Add a class HelloRequestHandler and enter the following code

using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Threading.Tasks;
using AppFunc = System.Func<System.Collections.Generic.IDictionary<string, object>, System.Threading.Tasks.Task>;

public class HelloRequestHandler
{
    private readonly AppFunc _next;
    public HelloRequestHandler(AppFunc next)
    {
        if(next == null)
        {
            throw new ArgumentNullException("next");
        }
        _next = next;
    }
    public Task Invoke(IDictionary<string, object> environment)
    {
        IDictionary<string, string[]> responseHeaders =
                (IDictionary<string, string[]>)environment["owin.ResponseHeaders"];
        var responseBytes = System.Text.ASCIIEncoding.UTF8.GetBytes(
                     string.Format("<h1>Hello world</h1>"));
        Stream responseStream = (Stream)environment["owin.ResponseBody"];

        responseHeaders["Content-Length"] = new string[] { responseBytes.Length.ToString(CultureInfo.InvariantCulture) };
        responseHeaders["Content-Type"] = new string[] { "text/html" };
        responseStream.Write(responseBytes, 0, responseBytes.Length);

        return _next(environment);
    }
}
  • Add HelloRequestHandler middleware to Startup class
public class Startup
{
  public void Configuration(IAppBuilder builder)
  {
      builder.Use(typeof(Logger));
      builder.Use(typeof(HelloRequestHandler));
  }
}
  • Press F5 and browse http://localhost:8080 we will see the result like this browser result

ASP.NET MVC5, WEB API 2, SignalR are compatible with OWIN, so we can compose middlewares or develop middlewares for our application's need.

Posted in  dotnet       owin   component