Hosting ASP.NET Web API in LinqPad

Today I stumbled upon an interesting Stackoverflow question, where the user was asking how to go about self-hosting Web API in LinqPad.

The question has gone unanswered since December, and I’m guessing even the OP forgot about it. However, I’d like to elaborate a bit about the topic. You certainly can host Web API in LinqPad, provided you plug in a quick work around – and we actually did hit a similar issue with scriptcs.

Understanding LinqPad

LinqPad is an absolutely terrific tool, which allows you to write complex C# without Visual Studio. To be able to answer our original Web API hosting question, we need to understand what LinqPad does under the hood. Unfortunately, we won’t be able to dig much beyond the rough overview LinqPad offers on its about page, since it’s closed source.

However the page also features a nice chart explaining the high levels of LinqPad. I hope Joseph will take no offense if I hotlink it here:

There is great amount of impressive stuff going on here, including lexical parsing, static code analysis, and ultimately code compilation. My first thought was that LinqPad is compiling in memory into a dynamic assembly, and Web API does not support controller discovery from such assemblies.

However, that is not the case – a quick check uncovered that LinqPad actually does write a DLL to a disk, and stores in the Temp directory:

However, it turns out, it also does compile everything as nested classes, wrapping all of your code with a UserQuery class.

And that’s exactly where the problem lies. You can write all the code required to run Web API self host in LinqPad, you can reference Web API DLLs, it will compile fine and execute, but it will not discover your controllers.

Nested controllers

Web API, in the RTM version, requires controller types to be public.

In LinqPad case, the controllers are visible but not public, but nested public. This causes the DefaultHttpControllerTypeResolver to ignore them. This issue was fixed on September 2, 2012, with this commit, but that was already after the release.

We can easily remedy that by writing our own resolver:

In this case, we ignore all the default Web API predicates and simply get all visible types that implement IHttpController (which, by the way, in my opinion should be the only constraint by default as well).

If we now register the controller resolver, we can run Web API self from LinqPad easily:

And there we go!

Web API hosted in LinqPad.