How to Write OWIN Middleware

In this post we explore the ways how we can write OWIN middleware.

The source code for the post can be found at https://github.com/DmitryZinchenko/blogWritingOwinMiddleware01 .

If you had a chance to read OWIN specification you must have noticed that it only explains what Open Web Interface for .NET is, names software actors involved but does not give much details regarding how to write middleware components. So, let’s take a look how we can do it.

SOLUTION

Let’s start by creating a solution that will have two projects – a console application which will start the application and a class library which will contain middleware implementation.

In Visual Studio 2013 go to FILE | New -> Project, expand Other Project Types and select Visual Studio Solutions. Give it a name WritingOwinMiddleware01 and hit OK button. Then go to FILE | Add -> New Project, select Console Application, give it a name SelfHost and hit OK button. And then go to FILE | Add -> New Project, select Class Library, give it a name Middlewares and hit OK button. Add a reference to Middlewares project to SelfHost project.

NUGET PACKAGES

Now we need to add NuGet packages containing Katana components to the projects. Open Package Manager Console and run these two commands:

Install-Package Owin -Version 1.0.0 -ProjectName Middlewares
Install-Package Microsoft.Owin.SelfHost -Version 3.0.1 -ProjectName SelfHost

Owin package contains IAppBuilder startup interface definition, but not implementation. Microsoft.Owin.SelfHost package includes components needed to host OWIN-based application in our console application. This package has dependencies on other packages, including Microsoft.Owin that provides helpful types and abstractions, including AppBuilder class, that is a Katana’s IAppBuilder interface implementation, Microsoft.Owin.Hosting that provides types for hosting and running OWIN-based application and Microsoft.Owin.Host.HttpListener  that provides OWIN server built on HttpListener class.

The reason I split the solution in two projects is to demonstrate, that in a raw form OWIN middleware depends on IAppBuilder interface only. There are ways to write middleware using Katana extension classes, but I’ll save that for another post.

REGIONS IN THE SOLUTION

For you to follow the progress as we build middleware component and see how the code changes I will create multiple regions and comment them out as we progress. I will refer to the specific region that matches the code at that moment. So, if I say that the following code matches listing #1, you will need to make sure that region is the only that has code that is not commented out.

// listing #1
namespace Middlewares
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
        }
    }
}

#region [ listing #2 ]
// must be commented out
#endregion

#region [ listing #3 ]
// must be commented out
#endregion

CONSOLE APPLICATION

The code for console application will start web application by providing the type for startup class and the URL the HTTP server to listen on.

using System;
using Microsoft.Owin.Hosting;

namespace SelfHost
{
    class Program
    {
        static void Main(string[] args)
        {
            string url = "http://localhost:5000/owin";

            using (WebApp.Start<Middlewares.Startup>(url))
            {
                Console.WriteLine("server is listening on {0}", url);
                Console.ReadLine();
            }
        }
    }
}

STARTUP CLASS

Let’s start implementing startup class. This class provides a method that adds middleware nodes to the OWIN function pipeline. At this point we just want our solution to build and the application to run.

// listing #1
namespace Middlewares
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
        }
    }
}

Now, if we build the solution and hit Ctrl+F5 to run it we’ll see that the console application is running.

first run

The application is not doing anything useful at this point and you can see that nothing is happening if you navigate your browser to http://localhost:5000/owin

Hit Enter to exit the console application.

CONFIGURATION METHOD

Let’s start implementing startup configuration method that will provide middlewares for OWIN pipeline.

As we see, in listing #1 this method take one argument of type IAppBuilder. Let’s take a look the definition of this interface.

using System ;
using System.Collections.Generic;

namespace Owin
{
    public interface IAppBuilder
    {
        IAppBuilder Use(object middleware, params object[] args);
        object Build(Type returnType);
        IAppBuilder New();
        IDictionary<string, object> Properties { get; }
    }
}

As we know, Katana provides a default implementation of IAppBuilder interface – AppBuilder type. Let’s look what MSDN says about AppBuilder.Use Method – “Adds a middleware node to the OWIN function pipeline.”. That’s what we need. The only problem is that the type of the middleware parameter is object, and it does not give any clue about its implementation details. So, what type should we use?

APPLICATION DELEGATE

If you recall, OWIN specification mentions application delegate of type

Func<IDictionary<string, object>, Task>

Is this the type we should be using for writing our middlewares? OWIN specs calls it the primary interface after all. Let’s find out.

BUILD METHOD SUMMARY

To get more clues, let’s take a look at the source code for AppBuilder.Use method, and see what its summary reads:

// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.

namespace Microsoft.Owin.Builder
{
    ///
<summary>
    /// A standard implementation of IAppBuilder
    /// </summary>

    public class AppBuilder : IAppBuilder
    {
        ///
<summary>
        /// Adds a middleware node to the OWIN function pipeline. The middleware are
        /// invoked in the order they are added: the first middleware passed to Use will
        /// be the outermost function, and the last middleware passed to Use will be the
        /// innermost.
        /// </summary>

        /// <param name="middleware">
        /// The middleware parameter determines which behavior is being chained into the
        /// pipeline.
        ///
        /// If the middleware given to Use is a Delegate, then it will be invoked with the "next app" in
        /// the chain as the first parameter. If the delegate takes more than the single argument,
        /// then the additional values must be provided to Use in the args array.
        ///
        /// If the middleware given to Use is a Type, then the public constructor will be
        /// invoked with the "next app" in the chain as the first parameter. The resulting object
        /// must have a public Invoke method. If the object has constructors which take more than
        /// the single "next app" argument, then additional values may be provided in the args array.
        /// </param>
        /// <param name="args">
        /// Any additional args passed to Use will be passed as additional values, following the "next app"
        /// parameter, when the OWIN call pipeline is build.
        ///
        /// They are passed as additional parameters if the middleware parameter is a Delegate, or as additional
        /// constructor arguments if the middle parameter is a Type.
        /// </param>
        /// <returns>
        /// The IAppBuilder itself is returned. This enables you to chain your use statements together.
        /// </returns>
        public IAppBuilder Use(object middleware, params object[] args)
        {
            // rest omitted for brevity
        }
    }
}

There are many interesting things to note from that summary, but us in the meantime the most interesting clue is that a middleware can be written as either a delegate or a Type. Let’s first explore how we can write middlewares using delegates.

FIRST ATTEMPT

Let’s take a look at listing #2, which shows our first attempt to write OWIN middleware that implements Func<IDictionary<string, object>, Task> type. The delegate takes environment dictionary and returns a completed task.

// listing #2
namespace Middlewares
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            Func<IDictionary<string, object>, Task> middleware = (IDictionary<string, object> env) =>
            {
                Task task = Task.FromResult(0);
                return task;
            };

            app.Use(middleware);
        }
    }
}

Let’s run our application by hitting Ctrl+F5 and see what we get. Looks like we got exception.

first middleware attempt

The exception message reads:

“Unhandled Exception: System.ArgumentException: No conversion available between System.Func`2[System.Collections.Generic.IDictionary`2[System.String,System.Object],System.Threading.Tasks.Task] and System.Collections.Generic.IDictionary`2[System.String,System.Object]. Parameter name: signature”

Let’s convert CLR types to something we used to to see what the message says.

“No conversion available between Func<IDictionary<string, object>, Task> and IDictionary<string, object>.”

So, it seems like there was some type mismatch. We do have IDictionary<string, object> in the signature of our delegate, but let’s try to make it Func<IDictionary<string, object>, Task>.

SECOND ATTEMPT

Let’s modify the signature of our delegate type and see what happens.

// listing #3
namespace Middlewares
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            Func<Func<IDictionary<string, object>, Task>, Task> middleware = (Func<IDictionary<string, object>, Task> next) =>
            {
                Task task = Task.FromResult(0);
                return task;
            };

            app.Use(middleware);
        }
    }
}

The solution compiles again. Let’s run our application by hitting Ctrl+F5. Got another exception.

second middleware attempt

This exception message reads:

“Unhandled Exception: System.ArgumentException: No conversion available between System.Threading.Tasks.Task`1[System.Int32] and System.Func`2[System.Collections.Generic.IDictionary`
2[System.String,System.Object],System.Threading.Tasks.Task].
Parameter name: signature”

or, in plain English

“No conversion available between Task<int> and Func<IDictionary<string, object>, Task>.”

Another type mismatch. We do have Task (but not Task<int> and it is OK for our experiments) in the signature of our delegate, so let’s try to make it Func<IDictionary<string, object>, Task>.

THIRD ATTEMPT

Let’s modify the signature of our delegate type again and see what happens. Is third time really a charm?

// listing #4
namespace Middlewares
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            Func<Func<IDictionary<string, object>, Task>, Func<IDictionary<string, object>, Task>> middleware = (Func<IDictionary<string, object>, Task> next) =>
            {
                Func<IDictionary<string, object>, Task> inner = (IDictionary<string, object> env) =>
                {
                    Task task = Task.FromResult(0);
                    return task;
                };

                return inner;
            };

            app.Use(middleware);
        }
    }
}

The solution compiles again. Let’s run our application by hitting Ctrl+F5. And this time – no exception! Let’s see what happens when we use our browser and navigate to http://localhost:5000/owin . The browser did not display anything but the application did not throw another exception as well.

So, we found a type that we need to implement for writing OWIN middleware.

Func<Func<IDictionary<string, object>, Task>, Func<IDictionary<string, object>, Task>>

But that type looks pretty long and intimidating. Let’s see what we can do with type aliasing.

TYPE ALIAS

You have probably already seen this type alias before

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

Let’s use it to clean up middleware delegate type:

Func<AppFunc, AppFunc>

and we can re-write our code to look a bit cleaner

// listing #5
namespace Middlewares
{
    using AppFunc = Func<IDictionary<string, object>, Task>;

    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            Func<AppFunc, AppFunc> middleware = (AppFunc next) =>
            {
                AppFunc inner = (IDictionary<string, object> env) =>
                {
                    Task task = Task.FromResult(0);
                    return task;
                };

                return inner;
            };

            app.Use(middleware);
        }
    }
}

APPLICATION DELEGATE TYPE VS. MIDDLEWARE TYPE

So, now we have to types – AppFunc and Func<AppFunc, AppFunc> which are pretty easy to get confused with. Try to remember that

  • AppFunc – is the type of the primary interface in OWIN, which can be used to access HTTP context and pass data between middlewares (via environment dictionary)
  • Func<AppFunc, AppFunc> – is the type that can be used to write middleware

CHAINING MIDDLEWARES

If we come back to the summary for AppBuilder.Use method we will notice this statement: “If the middleware given to Use is a Delegate, then it will be invoked with the “next app” in the chain as the first parameter.” What is this “next app” is for?

As it turned out, each middleware is given a reference to reference of application delegate, or AppFunc (IMPORTANT: do not confuse it with Func<AppFunc, AppFunc>, which is a delegate type for writing middlewares) that represents the next middleware in the OWIN pipeline. Each middleware has a chance to either to invoke the application delegate of the next middleware or short-circuit the pipeline, create a Task and return it, effectively preventing the next middleware from executing it’s logic.

How to short-circuit the pipeline you have already seen in listing #5, where our middleware got a reference to the application delegate of the next middleware. Instead of invoking that delegate, ours simply created a completed Task and and returned it fulfilling the requirements set in OWIN specs for application delegates.

Let’s see how can we invoke the application delegate of the next middleware in OWIN pipeline. We already know that we are getting the reference to the next application delegate as an object of type AppFunc. But what do we do with it?

Let’s go back to AppBuilder.Build summary again, where we will find “If the middleware given to Use is a Type… The resulting object must have a public Invoke method.”. Hmm… Why is that? If you remember, a middleware can be either a Delegate or a Type. So, the “AppFunc next” can be either and we should not care how it was written.

So, in case of a Type we already know that the object “AppFunc next” refers to should have a public method Invoke, but what about if it is a Delegate? If you recall from the MSDN documentation for the Delegate class, the CLR provides an Invoke method for each delegate type with the same signature as the delegate.

As you recall, the signature of the application delegate is Func<IDictionary<string, object>, Task>, which means it has only one input parameter of type IDictionary<string, object> and returns type of Task.

So, each application delegate, whether it is a Delegate or a Type must have a method with the
following signature:

public Task Invoke(IDictionary<string, object>);

Now we are ready to modify our middleware:

// listing #6
namespace Middlewares
{
    using AppFunc = Func<IDictionary<string, object>, Task>;

    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            Func<AppFunc, AppFunc> middleware = (AppFunc next) =>
            {
                AppFunc inner = (IDictionary<string, object> env) =>
                {
                    Task task = next.Invoke(env);
                    return task;
                };

                return inner;
            };

            app.Use(middleware);
        }
    }
}

Do the usual test – run the application by hitting Ctrl+F5 and then navigate your browser to http://localhost:5000/owin . There was no exception, even though I expected one.

DO WE NEED TO CHECK FOR NULL?

So, each middleware gets a reference to the object that is a application delegate that represents the next middleware in the pipeline. Logically, at some point the pipeline should end and the last middleware should receive a null reference representing the next AppFunc, right?

Our current code, listing #6, is that edge-case scenario, where we have only one middleware and logically the “AppFunc next” should be null. But when we ran our application everything worked fine. Why?

Let’s put a break point on the line 14 and this time run the application under debugger by hitting F5. After application starts, navigate to http://localhost:5000/owin to cause our middleware to handle the request.

// listing #6
namespace Middlewares
{
    using AppFunc = Func<IDictionary<string, object>, Task>;

    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            Func<AppFunc, AppFunc> middleware = (AppFunc next) =>
            {
                AppFunc inner = (IDictionary<string, object> env) =>
                {
                    Task task = next.Invoke(env);
                    return task;
                };

                return inner;
            };

            app.Use(middleware);
        }
    }
}

When the debugger stops at the break point, hover over “next”, right-click and select Quick Watch. In the dialog expand nodes as seen on the following image.

Quick Watch on next

Well, very interesting. Non only “next” is not null, but it also has an Invoke method with a familiar signature (Task Invoke(IDictionary<string, object>). And what is this “Completed” member of type Task that has a status RanToCompletion. What is going on? It seems like next.Invoke(env) returned a completed task. Is that true? And what is this Builder.NotFound type? To understand what’s going on you need to go back to the source code.

Take a look at the code for NotFound

// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.

namespace Microsoft.Owin.Builder
{
    ///
<summary>
    /// Simple object used by AppBuilder as seed OWIN callable if the
    /// builder.Properties["builder.DefaultApp"] is not set
    /// </summary>

    internal class NotFound
    {
        private static readonly Task Completed = CreateCompletedTask();

        private static Task CreateCompletedTask()
        {
            var tcs = new TaskCompletionSource<object>();
            tcs.SetResult(null);
            return tcs.Task;
        }

        public Task Invoke(IDictionary<string, object> env)
        {
            env["owin.ResponseStatusCode"] = 404;
            return Completed;
        }
    }
}

and then for AppBuilder

// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.

namespace Microsoft.Owin.Builder
{
    using AppFunc = Func<IDictionary<string, object>, Task>;

    public class AppBuilder : IAppBuilder
    {
        private static readonly AppFunc NotFound = new NotFound().Invoke;

        private readonly IList<Tuple<Type, Delegate, object[]>> _middleware;

        public AppBuilder()
        {
            _middleware = new List<Tuple<Type, Delegate, object[]>>();
            _properties[Constants.BuilderDefaultApp] = NotFound;
        }

		public IAppBuilder Use(object middleware, params object[] args)
        {
            _middleware.Add(ToMiddlewareFactory(middleware, args));
            return this;
        }

		private object BuildInternal(Type signature)
        {
            object app;
            if (!_properties.TryGetValue(Constants.BuilderDefaultApp, out app))
            {
                app = NotFound;
            }

            foreach (var middleware in _middleware.Reverse())
            {
                Type neededSignature = middleware.Item1;
                Delegate middlewareDelegate = middleware.Item2;
                object[] middlewareArgs = middleware.Item3;

                app = Convert(neededSignature, app);
                object[] invokeParameters = new[] { app }.Concat(middlewareArgs).ToArray();
                app = middlewareDelegate.DynamicInvoke(invokeParameters);
                app = Convert(neededSignature, app);
            }

            return Convert(signature, app);
        }
	}
}

So, in short, NotFound is also an OWIN middleware (we have not gotten to the point where we create middleares using Type yet though), whose Invoke method returns completed Task (isn’t what we did in listing #5?). AppBuilder uses NotFound as it’s default middleware, and when it is building the pipeline, it uses it as the last middleware. So, no, you do not need to check “AppFunc next” for null.

Another interesting piece of code is line 22 in the code for NotFound. Guess what it does if you do not provide any of the middleware for the pipeline? To see what happens, let’s go back to listing #1 for a moment and use Fiddler to make a GET request.

// listing #1
namespace Middlewares
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
        }
    }
}

Request

GET http://localhost:5000/owin HTTP/1.1
User-Agent: Fiddler
Host: localhost:5000

Response

HTTP/1.1 404 Not Found
Content-Length: 0
Server: Microsoft-HTTPAPI/2.0
Date: Sun, 08 Mar 2015 16:15:49 GMT

The reason you did not see this 404 Not Found in the browser is because the response message does not have any body and there is nothing for the browser to display. But if you used Web API client – you would definitely got 404.

WHAT HAPPENS WHEN?

Let’s go back to the current state of code, listing #6, and look at this twisted, pretzel-looking piece of code that represents our middlware. We receive an object of type AppFunc and we return an object of the same type. But how does the code work? What happens at what point? Let’s add some diagnostic output to our code.

// listing #7
namespace Middlewares
{
    using AppFunc = Func<IDictionary<string, object>, Task>;

    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            Func<AppFunc, AppFunc> middleware = (AppFunc next) =>
            {
                Console.WriteLine("OWIN pipeline is being built");

                AppFunc inner = (IDictionary<string, object> env) =>
                {
                    Console.WriteLine("handling HTTP request");
                    return next.Invoke(env);
                };

                return inner;
            };

            Console.WriteLine("adding middleware node");
            app.Use(middleware);
        }
    }
}

Run the application by hitting Ctrl+F5 and take a look at the output.

listing 7 startup

The first message was when we passed our middleware to Use, the second when the OWIN pipeline was built and the the last one – when the application finished startup sequence and HTTP server started listening for incoming HTTP request.

So, what happens when we actually send HTTP request? Navigate your browser to the familiar http://localhost:5000/owin and you will see a new message in the console window.

listing 7 handling

Make a few more requests

listing 7 handling 2

As you see, the first three messages were created during application startup, and the others – during request handling. Now you know what area of your code is responsible for what stage in your application’s life cycle. But why do I care?

MIDDLEWARE INITIALIZATION

As we saw, the implementation of the inner application delegate is responsible for handling requests. If you need to perform a middleware initialization before you are ready to handle requests – you need to put that code outside of the application delegate implementation.

Let’s say your component requires application key before continuing handling requests. If you would retrieve those keys during each request handling – that would be a terrible performance hit. So, what do you do?

// listing #8
namespace Middlewares
{
    using AppFunc = Func<IDictionary<string, object>, Task>;

    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            Func<AppFunc, AppFunc> middleware = (AppFunc next) =>
            {
                Console.WriteLine("retrieving API keys");
                var apiKeys = new List<string> { "123", "234" };

                AppFunc inner = (IDictionary<string, object> env) =>
                {
                    Console.WriteLine("validating API keys for each HTTP request");
                    apiKeys.ForEach(k => Console.WriteLine("API key: {0}", k));
                    return next.Invoke(env);
                };

                return inner;
            };

            Console.WriteLine("adding middleware node");
            app.Use(middleware);
        }
    }
}

Application delegate implementation has access to the apiKeys defined outside of it thanks to to C# language feature called closure (see lines 13 and 18). Actually, this code creates two closures – one for apiKeys and the other – for next. Let’s run the application and see what is going on.

listing 8

MIDDLEWARE WITHOUT INITIALIZATION

If your middleware has no need for initialization – you can simplify the code.

// original
Func<AppFunc, AppFunc> middleware = (AppFunc next) =>
{
	AppFunc inner = (IDictionary<string, object> env) =>
	{
		Task task = next.Invoke(env);
		return task;
	};

	return inner;
};
// simplified
Func<AppFunc, AppFunc> middleware = (AppFunc next) => (IDictionary<string, object> env) =>
{
    Task task = next.Invoke(env);
	return task;
};
// even more simplified
Func<AppFunc, AppFunc> middleware = next => env =>
{
    Task task = next.Invoke(env);
	return task;
};

So, our code will look like

// listing #9
namespace Middlewares
{
    using AppFunc = Func<IDictionary<string, object>, Task>;

    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            Func<AppFunc, AppFunc> middleware = next => env =>
            {
                Console.WriteLine("handling HTTP request");
                Task task = next.Invoke(env);
                return task;
            };

            Console.WriteLine("adding middleware node");
            app.Use(middleware);
        }
    }
}

PRE- AND POST-PROCESSING

So, currently due to return statement our middleware is able to do something useful only before it passes control to the next one in the pipeline. But can we do a post-processing? With the help of async/await we can! If you recall, Invoke returns a Task, which can be awaited, but to use await keyword we need to add make the internal application delegate asynchronous.

// listing #10
namespace Middlewares
{
    using AppFunc = Func<IDictionary<string, object>, Task>;

    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            Func<AppFunc, AppFunc> middleware = next => async env =>
            {
                Console.WriteLine("before");
                await next.Invoke(env);
                Console.WriteLine("after");
            };

            app.Use(middleware);
        }
    }
}

listing 10

I WANT PROOF

Does it actually work? Let’s add another middleware, chain them together and see what happens.

// listing #11
namespace Middlewares
{
    using AppFunc = Func<IDictionary<string, object>, Task>;

    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            Func<AppFunc, AppFunc> middleware1 = next => async env =>
            {
                Console.WriteLine("middleware1 before");
                await next.Invoke(env);
                Console.WriteLine("middleware1 after");
            };

            Func<AppFunc, AppFunc> middleware2 = next => async env =>
            {
                Console.WriteLine("middleware2 before");
                await next.Invoke(env);
                Console.WriteLine("middleware2 after");
            };

            app.Use(middleware1);
            app.Use(middleware2);
        }
    }
}

listing 11

We see that because we called Use for the middleware1 first and then for middleware2, the order of execution of middlewares is in the same order – first middleware1 and then middleware2.

But what happens if we revers the order of Use calls?

// listing #12
namespace Middlewares
{
    using AppFunc = Func<IDictionary<string, object>, Task>;

    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            Func<AppFunc, AppFunc> middleware1 = next => async env =>
            {
                Console.WriteLine("middleware1 before");
                await next.Invoke(env);
                Console.WriteLine("middleware1 after");
            };

            Func<AppFunc, AppFunc> middleware2 = next => async env =>
            {
                Console.WriteLine("middleware2 before");
                await next.Invoke(env);
                Console.WriteLine("middleware2 after");
            };

            app.Use(middleware2);
            app.Use(middleware1);
        }
    }
}

listing 12

And indeed, the order of middleware invocation has been reversed as well.

ARE YOU MY TYPE?

If you recall, AppBuilder.Build method summary mentioned that OWIN middleware can be either Delegate or Type. We’ve covered Delegate, now let’s look at Type. We already know that the Type has to have an Invoke method that has an environment dictionary as its first argument and must return a Task. But how does it get a reference to the next middleware in the pipeline? The answer is in the summary again – “If the middleware given to Use is a Type, then the public constructor will be invoked with the “next app” in the chain as the first parameter.”

To add the middleware to the pipeline you need to give Use the type of the class.

// listing 13
namespace Middlewares
{
    using AppFunc = Func<IDictionary<string, object>, Task>;

    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            app.Use(typeof(Middleware));
        }
    }

    internal class Middleware
    {
        private readonly AppFunc _next;

        public Middleware(AppFunc next)
        {
            _next = next;
        }

        public Task Invoke(IDictionary<string, object> env)
        {
            Console.WriteLine("handling HTTP request");
            return Task.FromResult(0);
        }
    }
}

listing 13

If we want to do pre- and post-processing as we did with delegate, we need to use async/await magic again.

// excerpt from listing 14
public async Task Invoke(IDictionary<string, object> env)
{
    Console.WriteLine("before");
    await _next.Invoke(env);
    Console.WriteLine("after");
}

listing 14

MIDDLEWARE INITIALIZATION AND PARAMETERIZATION

Because we are dealing with a regular C# class we already know how to initialize it. But can we provide additional parameters? The summary for AppBuilder.Use has answer for that question as well – “If the object has constructors which take more than the single “next app” argument, then additional values may be provided in the args array.”

// listing #15
namespace Middlewares
{
    using AppFunc = Func<IDictionary<string, object>, Task>;

    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            app.Use(typeof(Middleware), 10, "auth");
        }
    }

    internal class Middleware
    {
        private readonly AppFunc _next;
        private readonly int _number;
        private readonly string _name;

        public Middleware(AppFunc next, int number, string name)
        {
            _next = next;
            _number = number;
            _name = name;
        }

        public async Task Invoke(IDictionary<string, object> env)
        {
            Console.WriteLine("before. number: {0}, name: {1}", _number, _name);
            await _next.Invoke(env);
            Console.WriteLine("after. number: {0}, name: {1}", _number, _name);
        }
    }
}

listing 15

I WANT AN INSTANCE, NOT A TYPE

If you notice, in this case you provide the type to the IAppBuilder.Use function and do not instantiate the middleware yourself. But what if you want or need to create an instance of your middleware before you pass it to IAppBuilder.Use function?

To instantiate your middleware using constructor you need to be able to provide it with the reference to the application delegate (wich is of type AppFunc).  But you do not know what it is. And you do not know it for a reason – OWIN host wants to manage the OWIN pipeline on its own and you should not interfere with it.

So, what do you do? If you go back to the Katana source code you will notice that it refers to some constants used by AppBuilder class, which are

// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.

namespace Microsoft.Owin.Builder
{
    internal static class Constants
    {
        internal const string BuilderAddConversion = "builder.AddSignatureConversion";
        internal const string BuilderDefaultApp = "builder.DefaultApp";

        internal const string Invoke = "Invoke";
        internal const string Initialize = "Initialize";
    }
}

The last two, Invoke and Initialize, sound like methods and we already know that Invoke actually is. Let’s see if we find anything in the code for AppBuilder class that refers to the Initialize constant. And here it is.

// Instance pattern:
// public void Initialize(AppFunc next, string arg1, string arg2),
// public Task Invoke(IDictionary<...> env)
private static Tuple<Type, Delegate, object[]> ToInstanceMiddlewareFactory(object middlewareObject, object[] args)
{
	// rest omitted for brevity
}

Take a look at the comment, that refers to the “instance” pattern. Does it mean that if we want to create an instance of the middleware that it should contain those two public methods, one of which is named Initialize and accepts a parameter of type AppFunc? Let’s find out.

// listing #16
namespace Middlewares
{
    using AppFunc = Func<IDictionary<string, object>, Task>;

    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            var middleware = new Middleware();
            app.Use(middleware, 10, "auth");
        }
    }

    internal class Middleware
    {
        private AppFunc _next;
        private int _number;
        private string _name;

        public void Initialize(AppFunc next, int number, string name)
        {
            _next = next;
            _number = number;
            _name = name;
        }

        public async Task Invoke(IDictionary<string, object> env)
        {
            Console.WriteLine("before. number: {0}, name: {1}", _number, _name);
            await _next.Invoke(env);
            Console.WriteLine("after. number: {0}, name: {1}", _number, _name);
        }
    }
}

listing 16

SUMMARY

In this post we’ve got familiar with essential OWIN and Katana types and looked at the ways to write OWIN middlewares using delegates and types. These raw middlewares depend on IAppBuilder interface only.

  • IDictionary<string, object> is the type of the environment dictionary
  • AppFunc is the type of the application delegate, the primary interface in OWIN
  • Func<AppFunc, AppFunc> is the type you use to write OWIN middleware
  • Owin.IAppBuilder is the interface that defines application startup, including OWIN pipeline building process
  • Microsoft.Owin.Builder.AppBuilder is Katana’s implementation of Owin.IAppBuilder interface

REFERENCES

WHAT IS NEXT?

In the next post we’ll look at other ways how we can write OWIN middlewares with the help of
helper classes found in Microsoft.Owin NuGet package.

How to Write OWIN Middleware