Benefits of Types in Microsoft.Owin Namespace

In this post we explore the types found in Microsoft.Owin namespace as well as the reasons why would you use them.

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

What Is The Problem?

To understand the benefits of types in Microsoft.Owin namespace let’s take a look at the effort and shortcomings of writing OWIN middleware using only types defined in OWIN specification. The specification defines the environment dictionary “…that stores information about the request, the response, and any relevant server state”.  That includes information like HTTP method, request and response header values, query string, request and response body, etc.

The environment dictionary is defined as a dictionary of string and object

IDictionary<string, object>

To retrieve the value from the dictionary you need to provide a string key and then cast the returned object to appropriate type. The disadvantage of this approach is that you need to remember the type you are casting to, and since the value of the dictionary is object, Visual Studio IntelliSence is of no help at all. Here is an example of what you would do to obtain request method, headers and body.

Func<AppFunc, AppFunc> middleware = (AppFunc next) => (IDictionary<string, object> env) =>
{
    var method = (string) env["owin.RequestMethod"];
    var headers = (IDictionary<string, string[]>) env["owin.RequestHeaders"];
    var body= (Stream) env["owin.RequestBody"];
    ...
    return next.Invoke(env);
};

Also, if you remember from the MSDN, if you provide incorrect key value – you will get KeyNotFoundException. Let’s take a look at how much effort it takes to write OWIN middleware using this approach and then see how much help we can get from the types in Microsoft.Owin namespace.

Weakly Typed

The following simple OWIN Middleware demonstrates typical tasks for retrieving parts of HTTP request such as method, query string, headers, body and then providing parts of HTTP response – headers, status code, body.

Let’s assume that our simple Web API allows you to retrieve and store data about cars, but it can only handle HTTP GET and POST methods and requires API key. The primary purpose of this example is to demonstrate how to work with OWIN environment dictionary, not how to properly write Web API service.

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

    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            Func<AppFunc, AppFunc> middleware = (AppFunc next) =>
            {
                IEnumerable<string> apiKeys = new[] { "123", "987" };

                AppFunc inner = (IDictionary<string, object> env) =>
                {
                    Console.WriteLine(Environment.NewLine);

                    var method = (string) env["owin.RequestMethod"];
                    var path = (string) env["owin.RequestPath"];
                    var queryString = (string) env["owin.RequestQueryString"];

                    string apiKey = string.Empty;

                    foreach (var segment in queryString.Split('&amp;'))
                    {
                        var keyValuePair = segment.Split('=');
                        var key = keyValuePair[0];

                        if (key.Equals("apikey", StringComparison.InvariantCultureIgnoreCase))
                        {
                            apiKey = keyValuePair[1];
                            break;
                        }
                    }

                    var requestHeaders = (IDictionary<string, string[]>) env["owin.RequestHeaders"];

                    string contentType = string.Empty;
                    if (requestHeaders.ContainsKey("Content-Type"))
                    {
                        contentType = requestHeaders["Content-Type"][0];
                    }

                    string contentLength = string.Empty;
                    if (requestHeaders.ContainsKey("Content-Length"))
                    {
                        contentLength = requestHeaders["Content-Length"][0];
                    }

                    string accept = string.Empty;
                    if (requestHeaders.ContainsKey("Accept"))
                    {
                        accept = requestHeaders["Accept"][0];
                    }

                    string requestBody;
                    using (var requestContentReader = new StreamReader((Stream) env["owin.RequestBody"]))
                    {
                        requestBody = requestContentReader.ReadToEnd();
                    }

                    Console.WriteLine("Method: {0}", method);
                    Console.WriteLine("Path: {0}", path);
                    Console.WriteLine("Query String: {0}", queryString);
                    Console.WriteLine("API Key: {0}", apiKey);
                    Console.WriteLine("Content-Type: {0}", contentType);
                    Console.WriteLine("Content-Length: {0}", contentLength);
                    Console.WriteLine("Accept: {0}", accept);
                    Console.WriteLine("Request Body: {0}", requestBody);

                    // create HTTP response

                    if (apiKeys.Contains(apiKey))
                    {
                        var responseHeaders = (IDictionary<string, string[]>) env["owin.ResponseHeaders"];

                        if (method.Equals("GET", StringComparison.InvariantCultureIgnoreCase))
                        {
                            // pretend that we retrieved the object based on path
                            var responseBody = "{\"id\":\"10\", \"make\":\"Mercedes\", \"model\":\"C63 AMG\", \"engine\":\"V6\"}";

                            responseHeaders["Content-Type"] = new[] { "application/json" };
                            responseHeaders["Content-Length"] = new[] { responseBody.Length.ToString() };
                            env["owin.ResponseStatusCode"] = 200; // OK

                            using (var responseBodyWriter = new StreamWriter((Stream) env["owin.ResponseBody"]))
                            {
                                responseBodyWriter.Write(responseBody);
                            }
                        }
                        else if (method.Equals("POST", StringComparison.InvariantCultureIgnoreCase))
                        {
                            // pretend that we persisted the object and returning a new one with an identity value property
                            var responseBody = "{\"id\":\"17\", \"make\":\"BMW\", \"model\":\"M3\", \"engine\":\"V6\"}";

                            responseHeaders["Content-Type"] = new[] { "application/json" };
                            responseHeaders["Content-Length"] = new[] { responseBody.Length.ToString() };
                            responseHeaders["Location"] = new[] { "http://localhost:5000/api/cars/17" };
                            env["owin.ResponseStatusCode"] = 201; // Created

                            using (var responseBodyWriter = new StreamWriter((Stream) env["owin.ResponseBody"]))
                            {
                                responseBodyWriter.Write(responseBody);
                            }
                        }
                        else
                        {
                            env["owin.ResponseStatusCode"] = 405; // Method Not Allowed
                            responseHeaders.Add(new KeyValuePair<string, string[]>("Allow", new[] { "GET", "POST" }));
                        }
                    }
                    else
                    {
                        env["owin.ResponseStatusCode"] = 403; // Forbidden
                    }

                    return next.Invoke(env);
                };

                return inner;
            };

            app.Use(middleware);
        }
    }
}

That is a lot of type casting, checking for existing value, working with arrays. On top of that you have to know the environment dictionary key names.

Sample HTTP Requests

Let’s run our application and make a few HTTP requests using Fiddler.

request #1

GET http://localhost:5000/api/cars/10 HTTP/1.1
User-Agent: Fiddler
Host: localhost:5000
HTTP/1.1 403 Forbidden
Content-Length: 0
Server: Microsoft-HTTPAPI/2.0
Date: Sat, 21 Mar 2015 03:50:08 GMT

request #2

GET http://localhost:5000/api/cars/10?apiKey=123 HTTP/1.1
User-Agent: Fiddler
Host: localhost:5000
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 64
Server: Microsoft-HTTPAPI/2.0
Date: Sat, 21 Mar 2015 03:54:23 GMT

{"id":"10", "make":"Mercedes", "model":"C63 AMG", "engine":"V6"}

request #3

PUT http://localhost:5000/api/cars/?apiKey=123 HTTP/1.1
User-Agent: Fiddler
Content-Type: application/json
Accept: application/json
Host: localhost:5000
Content-Length: 43

{"make":"BMW", "model":"M3", "engine":"V6"}
HTTP/1.1 405 Method Not Allowed
Allow: GET,POST
Content-Length: 0
Server: Microsoft-HTTPAPI/2.0
Date: Sat, 21 Mar 2015 04:00:31 GMT

request #4

POST http://localhost:5000/api/cars/?apiKey=123 HTTP/1.1
User-Agent: Fiddler
Content-Type: application/json
Accept: application/json
Host: localhost:5000
Content-Length: 43

{"make":"BMW", "model":"M3", "engine":"V6"}
HTTP/1.1 201 Created
Content-Type: application/json
Content-Length: 54
Location: http://localhost:5000/api/cars/17
Server: Microsoft-HTTPAPI/2.0
Date: Sat, 21 Mar 2015 04:01:09 GMT

{"id":"17", "make":"BMW", "model":"M3", "engine":"V6"}

Microsoft.Owin Namespace

Let’s see what types are found in Microsoft.Owin namespace. Expand References node in Middlewares project and double-click on Microsoft.Owin.

Microsoft.Owin assembly

Object Browser will get open and display namespaces that exist in Microsoft.Owin NuGet package as of version 3.0.1. Expand Microsoft.Owin namespace.

Microsoft.Owin namespace

There are a number of useful types in this namespace, but for our example we will cover only OwinStartupAttribute, OwinContext, OwinRequest, OwinResponse and OwinMiddleware types.

OwinStartupAttribute

This assembly attribute is used to mark which class in assembly should be used for automatic startup. In our example we are using self-hosting option and specify what class to use during starup for building OWIN pipeline

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

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

but if we were using OwinHost.exe we had to rely on conventions or specify that startup class using OwinStartupAttribute

[assembly: OwinStartup(typeof(Middlewares.Startup))]

You can read more about OWIN startup class detection in this post.

OwinContext

This class implements IOwinContext interface and wraps OWIN environment dictionary and provides strongly typed accessors. The non-default constructor accepts the dictionary and then the object provides strongly typed access to properties representing HTTP request and response as well as the dictionary itself. You could also retrieve and store data from/to dictionary using strongly typed getters and setters.

  • Request – HTTP request specific properties
  • Response – HTTP response specific properties
  • Authentication – authentication middleware
  • Environment – OWIN environment dictionary
  • TraceOutput – host.TraceOutput environment value
  • Get<T>(key) – gets a value from environment dictionary or default(T) if not present
  • Set<T>(key, value) – sets a value in the environment dictionary
AppFunc inner = (IDictionary<string, object> environment) =>
{
    IOwinContext context = new OwinContext(environment);
    IOwinRequest request = context.Request;
    IOwinResponse response = context.Response;
    IDictionary<string, object> environment = context.Environment;

    Stream requestBodyStream = context.Get<Stream>("owin.RequestBody");
    context.Set<int>("owin.ResponseStatusCode", 200);

    return Task.FromResult(0);
};

OwinRequest

This class implements IOwinRequest interface and provides access to OWIN environment dictionary values those relate to HTTP request such as method, scheme, host, path, query string, cookies as well as provides strongly typed access to HTTP request header values and request body stream.

  • Environment – OWIN environment dictionary
  • Context – request context
  • Method – request method
  • Scheme – request scheme
  • IsSecure – true if request scheme is https
  • Host – Host header value
  • PathBase – request path base
  • Path – request path
  • QueryString – provides correct handling of query string vavlues
  • Query – query string collection
  • Uri – uri associated with the request
  • Protocol – protocol
  • Headers – request header dictionary
  • Cookies – collection for Cookie request header
  • ContentType – Content-Type header value
  • CacheControl – Cache-Control header value
  • MediaType – Media-Type header value
  • Accept – Accept header value
  • Body – request body stream
  • CallCancelled – cancellation token for the request
  • LocalIpAddress – local IP address
  • LocalPort – local port
  • RemoteIpAddress – remore IP address
  • RemotePort – remote port
  • User – IPrincipal object for the request
  • ReadFormAsync() – asynchronously reads and parses the request body as a form
  • Get<T>(key) – gets a value from environment dictionary or default(T) if not present
  • Set<T>(key, value) – sets a value in the environment dictionary
AppFunc inner = (IDictionary<string, object> environment) =>
{
    IOwinContext context = new OwinContext(environment);
    IOwinRequest request = context.Request;

    string method = request.Method;
    string path = request.Path.HasValue ? request.Path.Value : string.Empty;
    string queryString = request.QueryString.HasValue ? request.QueryString.Value : string.Empty;
    string apiKey = request.Query["apiKey"] ?? string.Empty;
    using (Stream requestBodyStream = request.Body)
    {
    }

    return Task.FromResult(0);
};

OwinResponse

This class implements IOwinResponse interface and provides access to OWIN environment dictionary values those relate to HTTP response such as status code, response phrase, content type, cookies as well as provides strongly typed access to HTTP response header values and response body stream.

  • Environment – OWIN environment dictionary
  • Context – response context
  • StatusCode – response status code
  • ReasonPhrase – response reason phrase
  • Protocol – protocol
  • Headers – response header dictionary
  • Cookies – collection for Set-Cookie response header
  • ContentLength – Content-Length response header value
  • ContentType – Content-Type response header value
  • Expires – Expires response header value
  • ETag – E-Tag response header value
  • Body – response body stream
  • OnSendingHeaders – event that fires when the response headers a sent
  • Redirect() – sets 302 response status code and Location header
  • Write() – writes to the response body stream
  • WriteAsync() – asynchronously writes to the response body stream
  • Get<T>(key) – gets a value from environment dictionary or default(T) if not present
  • Set<T>(key, value) – sets a value in the environment dictionary
AppFunc inner = async (IDictionary<string, object> environment) =>
{
    IOwinContext context = new OwinContext(environment);
    IOwinResponse response = context.Response;

    var responseBody = "OWIN FTW!";

    response.ContentLength = responseBody.Length;
    response.ContentType = "text/plain";
    response.StatusCode = 200;

    await response.WriteAsync(responseBody);
};

Strongly Typed

Now, let’s modify our sample code to see how much easier it would be writing OWIN middleware with above mentioned types.

// listing #2
[assembly: OwinStartup(typeof(Middlewares.Startup))]

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

    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            Func<AppFunc, AppFunc> middleware = (AppFunc next) =>
            {
                IEnumerable<string> apiKeys = new[] { "123", "987" };

                AppFunc inner = async (IDictionary<string, object> env) =>
                {
                    Console.WriteLine(Environment.NewLine);

                    var context = new OwinContext(env);
                    var request = context.Request;
                    var response = context.Response;

                    var method = request.Method;
                    var path = request.Path.HasValue ? request.Path.Value : string.Empty;
                    var queryString = request.QueryString.HasValue ? request.QueryString.Value : string.Empty;
                    var apiKey = request.Query["apiKey"] ?? string.Empty;

                    var contentType = request.ContentType;
                    var contentLength = request.Headers["Content-Length"];
                    var accept = request.Accept;
                    string requestBody;

                    using (var requestContentReader = new StreamReader(request.Body))
                    {
                        requestBody = await requestContentReader.ReadToEndAsync();
                    }

                    Console.WriteLine("Method: {0}", method);
                    Console.WriteLine("Path: {0}", path);
                    Console.WriteLine("Query String: {0}", queryString);
                    Console.WriteLine("API Key: {0}", apiKey);
                    Console.WriteLine("Content-Type: {0}", contentType);
                    Console.WriteLine("Content-Length: {0}", contentLength);
                    Console.WriteLine("Accept: {0}", accept);
                    Console.WriteLine("Request Body: {0}", requestBody);

                    // create HTTP response

                    if (apiKeys.Contains(apiKey))
                    {
                        if (method.Equals("GET", StringComparison.InvariantCultureIgnoreCase))
                        {
                            // pretend that we retrieved the object based on path
                            var responseBody = "{\"id\":\"10\", \"make\":\"Mercedes\", \"model\":\"C63 AMG\", \"engine\":\"V6\"}";

                            response.ContentType = "application/json";
                            response.ContentLength = responseBody.Length;
                            response.StatusCode = 200; // OK

                            await response.WriteAsync(responseBody);
                        }
                        else if (method.Equals("POST", StringComparison.InvariantCultureIgnoreCase))
                        {
                            // pretend that we persisted the object and returning a new one with an identity value property
                            var responseBody = "{\"id\":\"17\", \"make\":\"BMW\", \"model\":\"M3\", \"engine\":\"V6\"}";

                            response.ContentType = "application/json";
                            response.ContentLength = responseBody.Length;
                            response.Headers["Location"] = "http://localhost:5000/api/cars/17";
                            response.StatusCode = 201; // Created

                            await response.WriteAsync(responseBody);
                        }
                        else
                        {
                            response.StatusCode = 405; // Method Not Allowed
                            response.Headers["Allow"] = "GET,POST";
                        }
                    }
                    else
                    {
                        response.StatusCode = 403; // Forbidden
                    }

                    await next.Invoke(env);
                };

                return inner;
            };

            app.Use(middleware);
        }
    }
}

In my opinion, even though the amount of code is not drastically smaller, but it is definitely more legible and is strongly typed.

OwinMiddleware

The last type I would like to cover in this post is OwinMiddleware. It is an abstract base class for creating OWIN middleware as a type as opposed to delegate, the one we used so far.

The usage pattern is pretty simple – derive your class from OwinMiddleware and implement non-default constructor and Invoke method. The OwinMiddleware has Next property that represents the next middleware in the OWIN pipeline.

[assembly: OwinStartup(typeof(Middlewares.Startup))]

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

    public class Middleware : OwinMiddleware
    {
        // class members

        public Middleware(OwinMiddleware next) : base(next)
        {
            // initialization
        }

        public override async Task Invoke(IOwinContext context)
        {
            // middleware logic

            // invoke the next middleware in the OWIN pipeline
            await Next.Invoke(context);
        }
    }
}

Let’s see how our middleware looks like implemented as a descendant of OwinMiddleware class.

// listing #3
[assembly: OwinStartup(typeof(Middlewares.Startup))]

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

    public class Middleware : OwinMiddleware
    {
        private IEnumerable<string> _apiKeys;

        public Middleware(OwinMiddleware next) : base(next)
        {
            _apiKeys = new[] { "123", "987" };
        }

        public override async Task Invoke(IOwinContext context)
        {
            Console.WriteLine(Environment.NewLine);

            var request = context.Request;
            var response = context.Response;

            var method = request.Method;
            var path = request.Path.HasValue ? request.Path.Value : string.Empty;
            var queryString = request.QueryString.HasValue ? request.QueryString.Value : string.Empty;
            var apiKey = request.Query["apiKey"] ?? string.Empty;

            var contentType = request.ContentType;
            var contentLength = request.Headers["Content-Length"];
            var accept = request.Accept;
            string requestBody;

            using (var requestContentReader = new StreamReader(request.Body))
            {
                requestBody = await requestContentReader.ReadToEndAsync();
            }

            Console.WriteLine("Method: {0}", method);
            Console.WriteLine("Path: {0}", path);
            Console.WriteLine("Query String: {0}", queryString);
            Console.WriteLine("API Key: {0}", apiKey);
            Console.WriteLine("Content-Type: {0}", contentType);
            Console.WriteLine("Content-Length: {0}", contentLength);
            Console.WriteLine("Accept: {0}", accept);
            Console.WriteLine("Request Body: {0}", requestBody);

            // create HTTP response

            if (_apiKeys.Contains(apiKey))
            {
                if (method.Equals("GET", StringComparison.InvariantCultureIgnoreCase))
                {
                    // pretend that we retrieved the object based on path
                    var responseBody = "{\"id\":\"10\", \"make\":\"Mercedes\", \"model\":\"C63 AMG\", \"engine\":\"V6\"}";

                    response.ContentType = "application/json";
                    response.ContentLength = responseBody.Length;
                    response.StatusCode = 200; // OK

                    await response.WriteAsync(responseBody);
                }
                else if (method.Equals("POST", StringComparison.InvariantCultureIgnoreCase))
                {
                    // pretend that we persisted the object and returning a new one with an identity value property
                    var responseBody = "{\"id\":\"17\", \"make\":\"BMW\", \"model\":\"M3\", \"engine\":\"V6\"}";

                    response.ContentType = "application/json";
                    response.ContentLength = responseBody.Length;
                    response.Headers["Location"] = "http://localhost:5000/api/cars/17";
                    response.StatusCode = 201; // Created

                    await response.WriteAsync(responseBody);
                }
                else
                {
                    response.StatusCode = 405; // Method Not Allowed
                    response.Headers["Allow"] = "GET,POST";
                }
            }
            else
            {
                response.StatusCode = 403; // Forbidden
            }

            await Next.Invoke(context);
        }
    }
}

Other Types

There are a few other types in Microsoft.Owin namespace that deal with headers, forms, cookies, paths and query strings. I encourage you to investigate them on your own. The source code is exceptionally well written and documented.

Summary

In this post we’ve got familiar with types from Microsoft.Owin package.

  • Dealing with OwinContext is far better than with IDictionary<string, object>
  • OwinMiddleware type is another way to create OWIN middlewares

References

What Is Next?

In the next post we’ll continue investigating helper classes found in Microsoft.Owin NuGet package.

Benefits of Types in Microsoft.Owin Namespace