Until recently, if you wanted to write a .NET web application and run it on Windows, that generally meant creating an ASP.NET project, and then deploying it to IIS. For most use-cases, that was not that painful - it's pretty well tuned for supporting a typical request/response dependent web site. IIS is also very powerful and very configurable, which is both a blessing and a curse.
In my day job, we've built out several enterprise applications for interfacing and extending instant messaging platforms, like Microsoft Lync and IBM SameTime. Invariably, we need some kind of web interface for these applications, for configuring settings, displaying metrics, and so forth. Until the past year, we followed the standard pattern, with ASP.NET web applications on top of IIS. In our case, however, there were some pretty serious pain-points that would repeatedly arise:
- Complicated Deployments: The software we sell to our customers is distributed as an installer that they install on servers within their corporate networks. The tooling that we had to build our installers was not always the most powerful, and not well-suited to automatically installing Windows features and IIS roles required for our applications. I've lost track of the number of support calls that I have been on where a customer skipped installing prerequisite components, or missed some of the required IIS roles. Also, having to install an array of IIS roles and features for a very light-weight web application really feels like overkill.
- IIS Configuration Woes: Similarly, because IIS is so configurable, it's easy enough for some of the settings to get twiddled and break our applications. Particularly when one of our applications shares a server or IIS site with other applications (the Lync Server Web UI and SharePoint are common culprits), sorting out the interaction between global IIS settings, site-level settings, and settings for our applications can be needlessly complicated.
- Mismatches between standard IIS behavior and our applications' needs: ASP.NET on IIS is generally oriented around a low-persistence request/response model. Some of our applications have considerable amounts of background processing to perform their work, which doesn't fit this model very well. By default, IIS application pools are set to terminate applications if they have been idle (i.e. not served an HTTP request) in a relatively small amount of time, and also to recycle the application at set intervals. There are ways to get around this behavior, by disabling the idle timeouts and recycling intervals, or employing some other service to periodically ping a keep-alive method on the application. Or you can split the UI component off from the background processing and deploy that as an additional service, but that introduces the complexity of communicating between the two processes and requires installing and configuring an additional service. We've done both, but neither is particularly fun.
Clearly, we were not the only ones to run into these pain-points. Eventually, Microsoft released the OWIN framework, which is much more light-weight and modular web application model than traditional ASP.NET. Along with OWIN came Project Katana, which was the default implementation of OWIN. While OWIN can be integrated into ASP.NET running on IIS, one of the huge selling points of OWIN and Katana is that it makes it considerably easier to create a stand-alone light-weight web server, running out of a Windows Service or even a regular old desktop application.
Running a light-weight stand-alone web server offers a lot of benefits:
- No dependencies on IIS or ASP.NET. All that is required is the .NET Framework, which drastically cuts back on the complexity of checking for and installing prerequisites at deployment.
- Much simpler deployments. Since your application is basically just an .exe, deployments are much simpler, no need to register anything with IIS, setup application pools, or any of that mess. You can go as far as simply zipping up the application directory, unzip it on the target, run the executable, and have a web application up and running.
- Complete control over configuration. Generally with OWIN, all the configuration for your webserver is explicitly configured in code. All of the IIS control panel and web.config fiddling goes away, and you can specify exactly the behaviors expected.
- Application lifecycle is simpler. Your application can service any incoming HTTP requests using the OWIN HttpListener, which works on its own background threads, while your application performs any other processing. There aren't any idle timeouts or automatic recyclings, and your application runs until you decide to stop it.
This all sounds pretty excellent, and in practice it has been a pretty big win for us. However, one difficulty that we encountered was in trying to convert our existing ASP.NET MVC applications over to OWIN self-hosted versions. ASP.NET 5 has been available for some time as a release candidate, and should be available in a final version soon, but at the time that we were first investigating making the switch to OWIN, there was not any version of ASP.NET MVC that could be used with the self-hosted OWIN HttpListener. One option could have been to rewrite our applications to use WebAPI on the back-end and serve static HTML, with JavaScript to load in data from the API, but we had relatively mature applications that followed the MVC way of doing things, populating Razor cshtml files from model classes server-side, and so doing that kind of rewrite and all the necessary regression testing was not particularly attractive.
So we cast about for an alternative that would let us reuse more of our existing code, and came upon the Nancy web framework. While there are some differences in execution, Nancy follows roughly the same conceptual model as ASP.NET MVC, and also provides a view engine with support for Razor cshtml views. It also had a mature and simple-to-use OWIN integration package, so after some experimentation to determine feasibility, we jumped in and started converting over some of our applications, and it has been a great success for us.
With that justification out of the way, I'm going to go ahead a present a very barebones example of how to setup a self-hosted OWIN web application that uses Nancy and runs as either a console application or as a Windows service. The source code is available on GitHub, at https://github.com/ericrrichards/NancyOwinTemplate and you can also download this code as a Visual Studio 2013 project template.