All Posts

Self-hosting a .NET API: Choosing between OWIN with ASP.NET Web API and ASP.NET Core MVC 1.0

Intro

At uShip, our monolithic web application and the services supporting it are written in ASP.NET MVC, Web API, and hosted on IIS . We have begun the journey of transitioning to microservices. One of the important decisions we had to make early on was the choice of hosting model for our microservice APIs. We opted for a self-hosted solution, where we didn’t have to depend on the existence of IIS on a machine, instead allowing the application to create an instance of an HTTP server within its own process. Self-hosting also opens up the possibility for future Linux deployments. We invested a bit of time investigating OWIN and the new ASP.NET Core offering. Here’s what we found.

OWIN vs ASP.NET Core MVC 1.0

OWIN

OWIN is a specification that describes how web servers and web applications interact that has been around for quite a while. One can build applications on top of OWIN which removes the dependency on IIS, allowing self-hosting. Once the application is self-hosted, wrapping it in a Windows service allows Windows to help manage the application’s lifecycle.

ASP.NET Core MVC 1.0

ASP.NET Core MVC 1.0 (the framework formally known as ASP.NET 5 MVC 6) is a new web framework by Microsoft. It is not a successor to ASP.NET Web API 2.2 or MVC 5, the web frameworks built for .NET Framework 4.6 (the latest version of the full .NET Framework). Rather, it is an alternative web framework that one can use if their code can run on .NET Core, a re-imaging of the .NET Framework that includes a subset of the full .NET Framework and is cross platform. Web applications built with ASP.NET Core can be run on Kestrel, an HTTP server built for ASP.NET Core that will allow you to self-host your application.

The below are some of our reasons we chose self-hosting with OWIN instead of with Kestrel and ASP.NET Core:

  • Stability. The ASP.NET Core ecosystem as a whole is not yet stable. At time of writing ASP.NET Core is on RC1, but we have seen code interface changes, project file changes, major tooling changes, and so on. The bleeding edge is too bloody for us to be productive in a codebase our size.
  • Seamless upgrade. .NET Framework 4.6 is the natural upgrade path for us. Our software is more than 10 years old, and we have invested lots of time in learning various libraries, and have significant use of them throughout the entire codebase. A lot of these libraries (e.g,. NHibernate) are not yet compatible ASP.NET Core.
  • Maturity. Nothing beats software that has stood the test of time in production. Along with reliability, there is also a plethora of online documentation for OWIN and tutorials by people that have already run into the problems that we will inevitably run into.

The below will help you implement your own OWIN self-hosted application. While the implementation is OWIN-specific, the overall idea of self-hosting is very similar and will be much easier to port to ASP.NET Core than an IIS deployment would be.

Terms To Be Familiar With

Below are some terms that you should be familiar with before moving on to the implementation

  • OWIN: Open Web Interface for .NET. Acts as an adapter between web servers and web applications. This is a specification, not an implementation.
  • Middleware: “plugins” for OWIN. Similar to an IHttpModule in IIS. If using Web API, these middlewares run before and after the ASP.NET pipeline finishes.
  • Katana: Microsoft’s implementation of OWIN, a collection of NuGet packages for developing OWIN applications. A breakdown of the NuGet packages and their purposes are shown in the following diagram.
    katana-nuget-map
  • Topshelf: An opinionated framework for easily developing Windows services.

Self-hosted Web API Hello, World! Windows service with OWIN and Topshelf

Note: All code is available on GitHub.

  • In Visual Studio, create a new Console Application project called “OwinHelloWorld”
  • Install the Microsoft.AspNet.WebApi.OwinSelfHost NuGet package
  • Install the Topshelf NuGet package
  • Add the following code:
  • Run the application one of the following ways:
    • Hit F5 in Visual Studio to debug
    • Run the exe to run the application as a regular process. The exe is usually located in SolutionRoot/SelfHostDemo/bin/Debug/SelfHostDemo.exe
    • Manage the application as a Windows service
  • Hit http://localhost:9000/api/helloworld in your browser

Gotchas Encountered While Switching from IIS to a Self-hosted Model

It would be a bad to assume that you can simply port over your IIS-based codebase into a self-hosted model. The below are some gotchas that you may run into.

    • HttpContext.Current: This will be null. HttpContext is IIS based and will not be set when self-hosting with OWIN.. If you have any code that relies on HttpContext, HttpRequest, or HttpResponse, it will have to be rewritten to handle an HttpRequestMessage or HttpResponseMessage, the HTTP types provided by Web API. Fortunately, we still have access to CallContext provided by ASP.NET. This class can be used to provide per-request static semantics. We have written an OWIN Middleware that gives us the request scope behavior of HttpContext.Current using CallContext:
    • HttpRequestMessage.Content.ReadAsStreamAsync().Result: IIS let’s you read the request stream multiple times, but by default OWIN does not, not does it let you reset the stream after reading it once. A common reason people need to read the stream twice is to log the incoming request before the input body is deserialized by the framework. We have written an OWIN Middleware that copies the request stream into an in-memory buffer to get around this:
    • IIS-specific modules: When investigating the switch from IIS to self-hosted, we discovered we relied on ISAPI_Rewrite, an IIS module that rewrites URLs ala Apache’s .htaccess. If we wanted to keep such behavior, we would need to either write an OWIN middleware that does the same thing, or somehow get a reverse proxy to do it.

What the future holds

Once the ASP.NET Core MVC 1.0 ecosystem stabilizes, it may be a suitable alternative to building OWIN applications for most. But for now, writing a self-hosted application using OWIN might be the best choice for a pre-existing codebase. If you are one of the lucky few who is in a greenfield project, it is definitely worth building your application with Core in mind for an easy upgrade. For help on determining if your software can be ported to Core, see ApiPort.

  • This is a great article, but it doesn’t look like the Microsoft.AspNet.WebApi.OwinSelfHost or Topself nuget packages are compatible with .NET Core, which limits the portability of this solution. If the package owners decide to build a .NET Core version, then I’d be all over this 🙂

    • c_world_poster

      and i doubt they will be because (from what this article seems to say) Kestral is used instead of owin and Topself is about Windows services and .net core is about cross platform

  • Bennie Kloosteman

    Went down the same path but are seeing a issues with Owin Self Host so we are going down the Core part but since the tooling is immature we are compiling for 4.6 . Also we are using service fabric as a host.

    • c_world_poster

      what issues are you seeing? Just curious as the place i now work is using Owin with TopShelf.

  • Web applications have two sides, server (hosting) & pipeline (how responses are created for requests), asp.net core has a flexibility to customize both of them, for example you can develop asp.net web api based on owin pipeline, and instead of hosting that on top of owin self host (like what you said), you can host your app on top of asp.net core & kestrel. You can use owin pipeline in asp.net core pipeline, because asp.net core itself is an Owin implementation. You can host your asp.net core middlwares & owin middlewares on top of any owin server such as owin self host or nowin too, because asp.net core middlewares are owin host compatible. You can develop a server or request pipeline from scratch if you prefer by implementing interfaces like IServer. I prefer to use ASP.NET Web API OData on top of OWIN & ASP.NET Core with Kesterl, because I’ll have access to OData features + SignalR, and I can continue my development while these stuffs are going to be .net core friendly, so I can start using .net core too without changing any line of my codes in the future.

  • Pritesh Ostwal

    I am having issues using this thoughwhere on PC the large files are posted fine but can not be done the same way on MAC OSX with Mono. Any suggestions??

  • ayman metwally

    Great article ..
    What I knew that I can’t self-host MVC applications .. Wasn’t that true?

    • You definitely can (and should) self-host ASP.NET Core MVC applications. It gives you the ability to develop in and deploy to non-Windows environments, since you wouldn’t be depending on IIS. Even hosting in IIS simply forwards the IIS request to the self-hosted Kestrel server.

      That being said, I wouldn’t use the Kestrel server on the edge: I would have something like nginx sitting in front of it as a proxy, as it has been in production for much longer, and you get much more out of the box like load balancing.

      • Robert Grant

        Does self-hosting allow for the usual authentication methods such as Kerberos, SAML, etc?

        • Self-hosting should allow you to use those authentication methods (and any feature, really) as long as its functionality comes from application code (i.e. not an IIS module) and doesn’t have a dependency on HttpContext.Current.

  • neel bhatt
  • pgoostree

    Has anyone dealt with restarting the self host process if it shuts down for any reason?

  • jw

    I cannot seem to get past this error:

    “Type ‘Microsoft.Owin.OwinContext’ in assembly ‘Microsoft.Owin, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35’ is not marked as serializable.”

  • Peter Kottas

    Hello everybody, I found this topic while looking for a solution to a similar problem. Ended up implementing something that works pretty much like very (very) simplified Topshelf. You can easily run as console and/or install, uninstall and so one as a service. I think it can be pretty useful for somebody. You can find the code here : https://github.com/PeterKottas/DotNetCore.WindowsService and there’s nuget here as well https://www.nuget.org/packages/PeterKottas.DotNetCore.WindowsService/ . Enjoy 🙂 This is of course for pure .net core 1.1 apps.

  • Ken Hadden

    Thanks for posting this. Always nice to see a company share IP.