Owin, Katana and getting started

Introduction

This article describes an emerging open source specification, referred to as Owin – An Open Web Interface for .Net, what it is, and how this might be beneficial to the .Net technology stack. It will also provide a brief, concise look at how to get started with Owin and related technologies. In my initial investigations with Owin and how to play with it, I found lots of conflicting documentation and unclear ways of how to make it work and why. This article is an attempt to better articulate those steps so that you may save yourself lots of time and come to a clearer understanding in a much shorter time than I did.

Note: The code for this article can be download from here.

First, What is it?

Just in case you are not aware, a community driven project referred to as Owin is really gaining traction. Owin is a simple specification that describes how components in a HTTP pipeline should communicate. The details of what is in the communication between components is specific to each component, however there are some common elements to each. Owin itself is not a technology, just a specification.

I am going to gloss over many details here in order to remain concise, but at its very core, Owin describes 1 main component which is the following interface:

Func<IDictionary<string, object>,Task>

This is a function that accepts a simple dictionary of objects, keyed by a string identifier. The function itself returns a task. The object in the dictionary in this instance will vary depending on what the key is referring to.

More often, you will see it referenced like this:

using AppFunc = Func<IDictionary<string, object>,Task>

An actual implementation might look like this:

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

This is essentially how the “environment” or information about the HTTP context is passed around. Looking at the environment argument of this method, you could interrogate it as follows:

var httpRequestPath = environment[“owin.RequestPath”] as string; 
Console.WriteLine(“Your Path is: [{0}]”,httpRequestPath);

if a HttpRequest was being made to ‘http://localhost:8080/Content/Main.css” then the output would be:

Your Path is [/Content/Main.css]

In addition, while not part of the spec, the IAppBuilder interface is also core to the functioning of an Owin module (or ‘middleware’ in Owin speak):

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

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

The IAppBuilder interface acts as the ‘glue’ or host to bring any registered Owin compatible libraries/modules together.

So what? I can do that now without Owin.

Okay so it may not look ground breaking, but this is the core of Owin and key to understanding what it offers. Since we have a basic understanding of the how, I am going to jump to what it currently offers as a result of supporting this mechanism. With support of this simple mechanism, I can now write isolated components that deal with specific parts of functionality related to Http requests. I can then chain them together to build capabilities of my Http server. Internet Information Server does not need to get a look in. You can literally chain together Owin components to form a pipeline of only the necessary features you want. In addition, the components I write do not have to have specific references to any particular pipeline component, and yet can still take advantage of any Owin compatible component.

Basically you can build or use a custom host, then you can insert whatever custom modules into the Http request processing pipeline. Owin provides the specification for writing those modules that make it easy to insert into the chain.

Internet Information Services comes with a plethora of pipeline and request handlers, management functionality, knobs, dials and features that make a comprehensive web server. However many people want a lean, cut down web server with only the features they want. This provides a much leaner pipeline that can provide great performance, in addition to only providing the feature set you want, meaning a smaller surface area which can be beneficial from a complexity and sometimes a security perspective.

Quit yer jibba jabba fool, show me some code  MrT1

Yes yes, I will, but first, a diagram illustrating the previous paragraph. As already mentioned, Owin is just a specification of what interface to expose and how to work with that interface.In order for modules written to the Owin spec to be functional, they must exist in a host. So at a conceptual level, Owin compared to Internet Information Server looks like this:

slide1

Since we have an empty Owin host, we can programmatically add Owin compatible modules based on only what our needs are as illustrated below:

slide2

The diagram above shows an Owin host with 3 modules registered to be used, Static files,  Authentication and SignalR.

(Note: SignalR is a popular real-time web messaging/connection library and has been written as an Owin compatible module)

Are we there yet?

Ok, so lets finally write an Owin compatible module or library.

  1. Within Visual Studio, Create a new blank solution.
  2. Add a new class library project to it.
  3. Install the Owin nuget package using:
    Install-Package Owin
    (via the package manager console in Visual Studio or right click on the project in Visual Studio and select Manage Nuget Packages)
  4. Add a new class, lets call it TestLogger and paste in the following code:
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using AppFunc = Func<IDictionary<string, object>, Task>;
    public class TestLogger
    {
        private readonly AppFunc _next;
        public TestLogger(AppFunc next)
        {
            if (next == null)
            {
                throw new ArgumentNullException("next");
            }
            _next = next;
        }
        public Task Invoke(IDictionary<string, object> environment)
        {
            System.Diagnostics.Trace.WriteLine(string.Format("Hitting TestLogger, path: {0}", environment["owin.RequestPath"]));
            return _next(environment);
        }
    }

That is actually all you need to write an Owin compatible library. Strictly speaking, you don’t need the reference to the Owin nuget package but we will make use of that in the next part. All this module does is write out the contents of the request path to the trace output for each request that comes in. All we need to do is examine the environment that is provided to us through the environment variable.

However, we have a module but nothing to host it in and no way to tell it to be included as part of a web server pipeline. We need an Owin capable host that loads our module and houses the running code. We also need to programmatically configure that host to include our module. Much like Internet Information Server acts as the host for most web apps in .Net..

So, we are going to add a web project to our solution which will act as the entry point, allowing us to configure a module for use in the web request pipeline.

  1. Within Visual Studio, add a new empty MVC project (I used MVC4) to your current solution.
  2. You need to reference at least the Owin assemblies. In addition, we are going to reference the Owin HttpListener written by Microsoft to act as the actual Http server in our Owin pipeline. To do this:
    Install the Owin nuget package and the Microsoft.Owin.HttpListener package using:
    Install-Package Owin
    Install-Package Microsoft.Owin.Host.HttpListener -Pre

    (via the package manager console in Visual Studio or right click on the project in Visual Studio and select Manage Nuget Packages. Note that the Microsoft.Owin.HttpListener package is pre-release so we need include the –pre option.)
    After installing those packages, you should see the appropriate references in your project as shown in the screen grab below: proj-refs
  3. Add a new class to this MVC project called ‘Startup
  4. Paste in the following code:
public class Startup
{
    // Invoked once at startup to configure your application.
    public void Configuration(IAppBuilder builder)
    {
        builder.Use(typeof(TestLogger));
    }
}

Here you can see we are using an instance of IAppBuilder passed into our configuration method to tell the host to ‘Use’ our custom pipeline component, often referred to as ‘Middleware’ in Owin speak.

Owin components use conventions for easy configuration, so when the Owin host starts up and loads our assemblies, it looks for the Startup class, and also a ‘Configuration’ method which accepts an IAppBuilder instance, and calls that, providing the instance.

The final piece of the puzzle

Ok, we have our custom pipeline component, our middleware, and we have an entry point where we can build or configure our pipeline. We need a host process to load these assemblies and invoke them with the requisite information.

This is where Project Katana comes in. Katana is a Microsoft written generic Owin host. You can go grab the source of this project, compile and run it, but it is easier to just install it so you can call it from the command line. By far, the easiest way to do this is to install a tool called ‘Chocolatey’ which is like a Nuget package installer but for windows binaries.

(Side Note: Chocolately is an awesome tool. If you get nothing else from this post, just use Chocolately to install some software and keep it up to date. It is easy to use and has a heap of applications supported.)

To install Chocolotey, run the following from a command line (literally copy and paste into a command line/console window):
@powershell -NoProfile -ExecutionPolicy unrestricted -Command "iex ((new-object net.webclient).DownloadString('http://chocolatey.org/install.ps1'))" && SET PATH=%PATH%;%systemdrive%\chocolatey\bin

Once its installed, from the command line, simply type:
cinst Katana –pre

And Katana will be magically installed. Now opening up a command line/console window and typing ‘Katana’ will load and run the Katana application, which is our Microsoft written Owin host. Nothing will get loaded because we haven’t specified anything, but that is what is next.

We have written our custom Owin component, we have created our web application entry point used to configure our Owin pipeline and we have installed our host application, Katana, to glue it all together. So lets see in action.

First we need to tell our web project to NOT automatically use the current page when starting up. Rather, we want it to startup the Katana host, and tell Katana to use our assemblies. To do this:

  • Open up the properties of the web project in your solution and select the ‘Web’ section. You should see a screen similar to the one shown below:.

WebProjectKatanaStartupOptions

For clarification, the things you need to enter are:

Ensure the ‘Start External Program’ is selected and enter the full path to the Katana executable. I installed to the default location using Chocolately so mine is set at:

C:\Chocolatey\lib\Katana.0.20-alpha-20220-88\tools\Katana.exe

Set the command line arguments to:

-p8080 –v

This represent the port number of 8080 and enabling verbose mode

Enter the working directory where your web project is located. In my case it was:

D:\Glav.Owin.Middleware\Glav.Owin.Consumer.Test.BasicWebConsumer

  • Now hit F5 to run the app. You should see a console application launched which looks similar to the one below:

running-katana

Now remember, the only component we have injected into the Owin pipeline is our own custom logging component. Since we have included the Microsoft.Owin.Host.HttpListener package into our project, that assembly also gets included in the output. When Katana executes, if no specific Http server is defined, it will automatically look for the Microsoft.Owin.Host.HttpListener assembly and use that.

  • Again, we only have our logging component installed, so if we load a browser, a navigate to http://localhost:8080 , we wont see a web page but the console should show the logging output of our custom component as in the screen shot below:

browsing-to-katana

 

All that work, for that?

Yes, but now we have everything in place to easily add other components in the pipeline. In addition, now you should have a reasonable understanding of the various pieces at play.  Remember, we have created a custom web server that only does exactly what we want it to.So conceptually, what we have created looks roughly like the following:

custom-katana-pipeline

Now lets create another component but I don’t want to create another project for that.

Add the following method block to your ‘Startup’ class in the web project in your solution:

// Invoked once per request.
public Task Invoke(IDictionary<string, object> environment)
{
   var responseBytes = System.Text.ASCIIEncoding.UTF8.GetBytes(
            string.Format("Serviced request on {0} at {1}",DateTime.Now.ToLongDateString(), DateTime.Now.ToLongTimeString()));
    Stream responseStream = (Stream)environment["owin.ResponseBody"];
    IDictionary<string, string[]> responseHeaders =
        (IDictionary<string, string[]>)environment["owin.ResponseHeaders"];
    responseHeaders["Content-Length"] = new string[] { responseBytes.Length.ToString(CultureInfo.InvariantCulture) };
    responseHeaders["Content-Type"] = new string[] { "text/plain" };
    return responseStream.WriteAsync(responseBytes, 0, responseBytes.Length);
}

Then add this line of code as the last line in the ‘Configuration’ method within the ‘Startup’ class.

builder.Use(new Func<AppFunc, AppFunc>(ignoredNextApp => (AppFunc)Invoke));

Now, hit F5 to run your app, and browser to http://localhost:8080

You should see a response in the browser similar to the screen grab shown below:

browsing-to-katana2

That code we added in the Invoke method, did the following:

  • Created a simple text response as a byte array.
  • Grabbed the response body stream and the response headers object from the environment variable using standard Owin defined key names.
  • Set the response headers according to the response itself.
  • Wrote the bytes to the response stream.

In order to use the code in the Invoke method, we needed to tell our pipeline to use it. This was achieved in the Configuration method via the line:

builder.Use(new Func<AppFunc, AppFunc>(ignoredNextApp => (AppFunc)Invoke));

This simply injected the delegate for our Invoke function into the pipeline. So now our comceptual pipeline looks like this:

final-pipeline

All without any real dependencies and in a relatively small amount of code.

And you made it

After all that, you can finally see how composable and modular the Owin concepts and architecture are. There are quite a few Owin compatible middleware modules out there such as SignalR, FubuMVC, NancyFx to name a few. These can be added to your pipeline and you then have the power that each brings at your disposal.

This is just the beginning. Imagine being able to easily build a custom web server with only the capabilities you need. An open, composable and modular world with no lock in. Sounds good to me. Hopefully the Owin concepts and goals are a little clearer now.

Remember, the code for this article can be downloaded from here.

10 Comments

  • Your articles are always interesting and understandable. Thank you!

  • Great post! Nice job putting all the information in one place and connecting it together. I finally understand how Owin and Katana work and what they are about.

  • Thanks John. Thats exactly why I wrote the article. Glad it helped.

  • I never heard both these term before however after reading your fantastically articulated demonstration I now know what exactly OWIN and Katana is.

    Will try to make use of these very soon.

  • hm, something should be missing from the setup description. when I start the project with the settings given above katana complains it cannot find an entry point.

  • Hi Bond,

    Sounds like you are missing the Http listener part. Ensure you have the appropriate reference listed. Try downloading the solution from the link provided and compare differences.

  • I can't find Katana on chocolaty.
    That it been removed? Or Is your post pre-empting it?

  • Hi Darcy, it would appear it has now been renamed to OwinHost. If you do a:

    clist owinhost -pre

    you will see it listed on chocolatey

    I need to update this post which I will do shortly.

  • Can you show how to add a ConcurrentDictionary at the beginning of the OWIN pipeline, and then access it at the end of the pipeline, right before sending a response to the HTTP caller?

  • World class explanation! FINALLY something meaningful and straightforward about all that OWIN thing. I was heavily confused with OWIN when first installed VS 2013 and MVC 5.

    However, it would be great if you could explain further how Owin auth fits in MVC 5 applications which use IIS pipeline.

Comments have been disabled for this content.