My last post about OWIN covered a little bit about the different hosting options, and then quite a bit about OWIN middleware. However, I found the hosting coverage to be a little weak, so I thought I would do one more, much shorter post, on just the different hosts available.
As mentioned before, there are 4 different OWIN hosts available from Microsoft. 3 from project Katana and one from project Helios.
Actually, there are 5. There is also a test host that can be used to test OWIN middleware in Unit tests etc in-memory, instead of having to open a port and listen for incoming requests…
The first, and simplest to get started with is the Katana self-host. But since we saw that being used in the last post, I will skip that one…
Owin Web host
The next host out of Katana is the Web host, which enables us to host OWIN in IIS together with ASP.NET.
The easiest way to get going with the Web host is to create a new ASP.NET project. And as of a fairly late release of ASP.NET, you will get OWIN automagically. Just look at the Startup.cs file in the root of the application…
If you open the Startup.cs file, you will see that the only thing that is happening in the Configuration() method is a call to ConfigureAuth(), which is defined in a separate file called Startup.Auth.cs, located in the App_Start folder…
In this case, we are not really interested in the auth stuff, and instead focused on the OWIN stuff, so I will just ignore the Startup.Auth.cs file…
Instead, I will add the same simple diagnostics middleware as I did in my previous post, but instead of doing Console.WriteLine() I use Debug.WriteLine(). Like this
public void Configuration(IAppBuilder app)
{
ConfigureAuth(app);
app.Use(async (context, next) =>
{
var watch = new Stopwatch();
watch.Start();
await next();
watch.Stop();
Debug.WriteLine("Request took {0} ms", watch.ElapsedMilliseconds);
});
}
Running my application, and looking at Visual Studio’s Immediate window, I get this
Nice and simple!
But what if I didn’t want it as a Debug.WriteLine(). What if I wanted it to be visible in some other way? Well, how about adding it to the end of the response?
Modifying the implementation like this
app.Use(async (context, next) =>
{
...
context.Response.Write(string.Format("<!-- Request took {0} ms -->", watch.ElapsedMilliseconds));
});
will give us this
That is one simple, but still powerful way to plug into the ASP.NET pipeline…
Microsoft also gives us the ability to plug in at different key times in the pipeline by using the UseStageMarker() method. This method is called _after_ the middleware is added. So if you want to make sure your middleware is called during the authentication part of the ASP.NET pipeline, you do it like this
app.Use((context, next) => ... );
app.UseStageMarker(PipelineStage.Authenticate);
The call to UseStageMarker will affect any middleware added to the pipeline before the call, but after the last call to UseStageMarker. So you can add multiple middleware components at different events like this
// Will run during Authenticate step
app.Use((context, next) => ...);
app.Use((context, next) => ...);
app.UseStageMarker(PipelineStage.Authenticate);
// Will run during Authorize step
app.Use((context, next) => ...);
app.UseStageMarker(PipelineStage.Authorize);
One thing to note is that the Web host plugs into the ASP.NET pipeline through an IHttpModule. This means that the OWIN pipeline is only run when requesting resources that run through this pipeline. That means that requests for things like static resources won’t come through this pipeline. If you want that, you need to add the “runAllManagedModulesForAllRequests” attribute to the “modules” element in the web.config tile. Just remember that that means that ALL requests come through this pipeline, including things like requests for favicon.ico and so on…
Ok, enough about the Web host. There are more hosts to cover!!!
OwinHost.exe
Let’s look at OwinHost.exe instead… To do so, we need to create a Class Library project with the stuff we want. (Actually, it shouldn’t be necessary to use a class library, but it makes the most sense…)
So, I create a new Class Library project and NuGet Microsoft.Owin and OwinHost, which will download the OwinHost.exe and open up a fairly dense “readme.txt” file containing a lot of information…
Next, rename the Class1.cs file to Startup.cs and add a Configuration() method like this
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.Use((context, next) =>
{
context.Response.Write("Hello World");
return Task.FromResult(0);
});
}
}
Next up is to get OwinHost.exe to run it for us…
The actual OwinHost.exe file gets added to the NuGet packages folder under “OwinHost.<version>/tools”.
The way you call OwinHost.exe is by just calling
OwinHost <Startup Class Name>,<Assembly Name>
In my case, that is
OwinHost DarksideCookie.Owin.OwinHost.Startup,DarksideCookie.Owin.OwinHost
DISCLAIMER! To be honest, you are supposed to be able to have it auto-locate your class using the OwinStartupAttribute and such things. But the only way I could get it to work was by copying my assembly to the same folder as the OwinHost.exe file and run the above command. Far from a good solution, but I didn’t feel like spending ages on getting it to work…
Ok, so OwinHost.exe is a great way of just getting something up and going. Unfortunately, with the amount of problems I had getting it going, I’m not sure it is my favorite…
Project Helios
The last host I will be looking at is Project Helios, which is a way to host OWIN in IIS without having to have ASP.NET included…
To start this off, I create a new ASP.NET project. However, in this case, I will go for an empty project. I don’t really want ASP.NET at all…
And don’t forget to update the project to .NET 4.5.1. I did, and that resulted in the NuGet package we are about to install to rollback. Unfortunately it also left my targets files in a somewhat non-working order. So I had to restart VS…
Next I NuGet Microsoft.Owin.Host.IIS. Remember that it is a pre-release at this time, so if you use the Package Manager Console, you need to add “–pre”. Once that package is installed, we can add the “standard” Startup.cs class, and some configuration… And then, F5… That’s it!
The cool thing about Project Helios is, as mentioned in the last post, that it is not dependent on ASP.NET and System.Web. This makes hosting OWIN in IIS much les resource intensive, and much closer to the metal. The Helios host plugs into IIS native APIs instead of through the ASP.NET pipeline.
Testing host
Ok, that was another, slightly deeper look at the hosting options available for OWIN. The last host I want to have a quick look at is not actually a real host as such. It is an in-memory host that can be used for testing…
To demo this, create a new Class Library project and NuGet Microsoft.Owin.Testing and Nunit (or whatever testing framework you like). This will give you another “readme.txt” that you can either skim through, or jus ignore as you have me telling you what you need to do…
The next thing is to change the Class1.cs into a test class. In my case, that means changing it into this
[TestFixture]
public class Test
{
[Test]
public async void Server_responds_with_Hello_World()
{
}
}
Next I use the OWIN test host, which is a little different than the other hosts in that it doesn’t require a Startup class. Instead, it takes an Action<> that does the configuration
[TestFixture]
public class Test
{
[Test]
public async void Server_responds_with_Hello_World()
{
using (var server = TestServer.Create(app =>
{
app.Use((context, next) =>
{
context.Response.Write("Hello World");
return Task.FromResult(0);
});
}))
{
}
}
}
And finally, I can use the “server.HttpClient” property to get hold of an HttpClient instance that will send requests to the in-memory server. And using that, I can make a simple request, and validate the response
[TestFixture]
public class Test
{
[Test]
public async void Server_responds_with_Hello_World()
{
using (var server = TestServer.Create(app =>...))
{
var response = await server.HttpClient.GetAsync("/");
Assert.AreEqual("Hello World", response.Content.ReadAsStringAsync().Result);
}
}
}
That’s it! It is THAT simple to test OWIN hosted middleware!
Of course, repeating the middleware config in every test is not the best solution, but nothing stops you from extracting that into its own method.
Now you have seem the different hosts available from Microsoft, including the awesome test host that will make testing OWIN-based code nice and simple!
That’s it for this time, but once again, as usual, the code is available here: DarksideCookie.Owin.Hosts.zip (883.15 kb)
Sorry for the large download! Blame Microsoft for making standard ASP.NET MVC projects so freaking large…
Cheers!