Last time we took a look at IBuilder in vNext, so this time it only makes sense to talk about OWIN.

OWIN is a specification which is created, maintained, and evolved by the .NET HTTP Abstractions working group. It is described on its landing page in the following way.

OWIN defines a standard interface between .NET web servers and web applications. The goal of the OWIN interface is to decouple server and application, encourage the development of simple modules for .NET web development, and, by being an open standard, stimulate the open source ecosystem of .NET web development tools.

Within the OWIN specification you will find the definition of an AppFunc as Func<IDictionary<string, object>, Task>. This function is invoked once per request and returns a Task which is completed when that work is finished. The IDictionary<string, object> provided in the call is the OWIN Environment and it contains all of the fundamental information you will find in an HTTP request and response. More details than that are beyond the scope of this article. :)

In ASP.NET today you will find our OWIN support coming from software in the KatanaProject solution, but in ASP.NET vNext we are supporting OWIN in a different way. Some of the reasons for that are technical - but even more significantly than that - changing how we support OWIN is based on a considerable amount feedback we received from C# OSS developers. For example, IAppBuilder shouldn't be positioned as the only way to create an OWIN pipeline. Another point of feedback was that the various wrapper classes like OwinMiddleware, OwinRequest, and OwinResponse can cause confusion because the OWIN specification itself is type-less.

So, what does OWIN support look like ASP.NET vNext?

Great question! We want to be sure that the OWIN scenarios supported in KatanaProject is also available on vNext. Specifically we want to be able to add OWIN middleware to the pipeline, use our components as OWIN middleware, and run our pipeline on an OWIN http server. The techniques we have used to make that possible in the vNext preview is based on the ongoing discussions of the working group, and will continue to evolve as the working group and the OWIN specification evolves.

To use OWIN middleware, in a nutshell, there is a BuilderFunc with a very specific Action signature. This Action may then be invoked for each OWIN middleware you want to add to the pipeline. In vNext from the Startup Configure you can get to this BuilderFunc action by calling the IBuilder.UseOwin extension method.

To see what this looks like let's write "Hello World!" in response to all requests.

using System;  
using System.Collections.Generic;  
using System.IO;  
using System.Text;  
using Microsoft.AspNet.Builder;

public class Startup  
{
    public void Configure(IBuilder app)
    {
        var buildFunc = app.UseOwin();

        buildFunc(next => async env => {
            // Get some OWIN keys from the environment
            var responseHeaders = 
                (IDictionary<string, string[]>)env["owin.ResponseHeaders"];
            var responseBody = 
                (Stream)env["owin.ResponseBody"];

            // Set the content type and write some data
            responseHeaders["Content-Type"] = new[]{"text/plain"};
            var data = Encoding.UTF8.GetBytes("Hello world!");
            await responseBody.WriteAsync(data, 0, data.Length);
        });
    }
}

You can see this running by running the following from a command prompt, and browsing to http://localhost:5000

git clone https://github.com/loudej/WheresLouSamples  
cd WheresLouSamples\04.Owin  
go  

This shows running OWIN middleware in a vNext, and there is also the ability to do the reverse - you can call a BuildFunc.UseBuilder() extension method which returns an IBuilder that can add vNext middleware onto the OWIN pipeline.

The fact that the BuildFunc is very distinct also enables you to write extension methods onto it which gives you some nice syntax sugar when add OWIN middleware to the pipeline. To demonstrate that, let's try porting the UseLogRequests extension method from the previous article as pure OWIN middleware.

using System;  
using System.Collections.Generic;  
using System.Diagnostics;  
using System.IO;  
using System.Text;  
using System.Threading;  
using System.Threading.Tasks;  
using Microsoft.AspNet.Builder;

namespace MyApp  
{
    using AppFunc = 
        Func<IDictionary<string, object>, Task>;

    using BuildFunc = Action<Func<
        Func<IDictionary<string, object>, Task>,
        Func<IDictionary<string, object>, Task>
    >>;

    public class Startup 
    {
        public void Configure(IBuilder app)
        {
            BuildFunc build = app.UseOwin();

            // Example using a pure OWIN extension method
            build.UseLogRequests("OWIN Middleware");

            // Handle all requests by writing out request headers 
            // and OWIN environment 
            build(next => async env => {
                var requestHeaders = 
                    (IDictionary<string, string[]>)
                    env["owin.RequestHeaders"];
                var responseHeaders = 
                    (IDictionary<string, string[]>)
                    env["owin.ResponseHeaders"];

                var responseBody = 
                    (Stream)
                    env["owin.ResponseBody"];

                using (var responseWriter = 
                    new StreamWriter(responseBody, Encoding.UTF8))
                {
                    responseHeaders["Content-Type"] = new[]{"text/plain"};

                    await responseWriter.WriteLineAsync(
                        "=== Request Headers ===");

                    foreach(var header in requestHeaders)
                    {
                        await responseWriter.WriteLineAsync(
                            header.Key + ": " + 
                            String.Join(", ", header.Value));
                    }

                    await responseWriter.WriteLineAsync("");
                    await responseWriter.WriteLineAsync(
                        "=== OWIN Environment ===");

                    foreach(var entry in env)
                    {
                        await responseWriter.WriteLineAsync(
                            entry.Key + ": " + 
                            String.Join(", ", entry.Value));
                    }

                }
            });
        }
    }

    public static class LogRequestsExtensions
    {
        public static BuildFunc UseLogRequests(
            this BuildFunc build, string label)
        {
            build(next => new LogRequestsMiddleware(next, label).Invoke);
            return build;
        }
    }

    public class LogRequestsMiddleware
    {
        AppFunc _next;
        int _requestCount;
        string _label;

        // called once when pipeline is built
        public LogRequestsMiddleware(AppFunc next, string label)
        {
            _next = next;
            _label = label;
        }

        // called once per request
        public async Task Invoke(IDictionary<string,object> env)
        {
            var sw = new Stopwatch();
            sw.Start();
            var requestNumber = Interlocked.Increment(
                ref _requestCount);

            // request is incoming
            var requestMethod = 
                (string)env["owin.RequestMethod"];
            var requestPathBase = 
                (string)env["owin.RequestPathBase"];
            var requestPath = 
                (string)env["owin.RequestPath"];
            var requestQueryString = 
                (string)env["owin.RequestQueryString"];

            Console.WriteLine(string.Format(
                "{0} #{1} incoming {2} {3}{4}{5}", 
                _label,
                requestNumber,
                requestMethod,
                requestPathBase,
                requestPath,
                requestQueryString));

            // pass control to following components
            await _next(env);

            var responseStatusCode = 
                (string)env["owin.ResponseStatusCode"];

            // call is unwinding
            Console.WriteLine(string.Format(
                "{0} #{1} outgoing {2} {3}ms", 
                _label,
                requestNumber,
                responseStatusCode,
                sw.ElapsedMilliseconds));
        }
    }

}

You can run this example with the following.

git clone https://github.com/loudej/WheresLouSamples  
cd WheresLouSamples\05.Owin  
go  

Then when you browse to http://localhost:5000/hello/world?foo=bar you should see timings for request written to console output, and details about request headers and OWIN environment written the web browser.

Of course, this is just an example and not specific guidance about how to structure your own OWIN middleware. If you're curious about that or want to learn more, I'd strongly encourage checking out the discussion group and reaching out to the folks on twitter.

Now let's see that running on Nowin

David Fowler suggested there should also be an example of running OWIN and vNext components on Nowin, which is an open source OWIN server. BuildFunc isn't official yet, so you'll have to forgive some of the extra lines of code which make this sample work. Here is a Program.Main which puts the OWIN logging middleware we just made, and a vNext .Run(HttpContext) handler, together on top of Nowin as a single AppFunc.

    public class Program  
    {
        static AppFunc notFound = async env => 
            env["owin.ResponseStatusCode"] = 404;

        public void Main(string[] args) 
        {
            // List.Add is same signature as BuildFunc
            IList<MidFunc> list = new List<MidFunc>();
            Configure(list.Add);

            // Now chain middleware together in reverse order
            AppFunc app = list
                .Reverse()
                .Aggregate(notFound, (next, middleware) => 
                    middleware(next));

            // Finally start OWIN server
            var server = ServerBuilder.New().SetPort(5000).SetOwinApp(app);
            using (server.Start())
            {
                Console.WriteLine("Listening on port 5000.");
                Console.WriteLine("Enter to exit.");
                Console.ReadLine();
            }
        }

        public void Configure(BuildFunc build)
        {
            // OWIN middleware
            build.UseLogRequests("OWIN Middleware");

            // adding vNext component in OWIN pipline
            build.UseBuilder().Run(async context =>
            {
                Console.WriteLine("Returning Hello World");
                context.Response.ContentType = "text/plain";
                await context.Response.WriteAsync("Hello World!");        
            });
        }
    }

And this final example can be run with:

git clone https://github.com/loudej/WheresLouSamples  
cd WheresLouSamples\06.Owin  
go