To use them in view, next step in Asp.Net would be to drag&drop them into view, css in <head> and scripts to bottom of <body>. VS produces proper tags for them:
If you run application now, you can see that all already works, everything loads just fine:
That is very nice, as by default OWIN doesn’t serve static resources (you must configure simple FileServer, which you can do anyway if you want to enable file browsing in some of your folders, but then add builder.UseNancy() line at end of Configure method, as Nancy handler is greedy and it will handle request before it gets to file server). But even without it, this works because of default conventions in Nancy, which are summed in first sentence on that page: stick stuff in /Content .. done.
As a side note, notice that everything is loaded within 200ms,
which is nice, especially when having in mind that average
human needs 300-400ms to perform an blink of eye 🙂
So, this makes again another very simple blog post, to summarize plot started by the title, there is nothingneeded to do to serve static resources,if you use Nancy on OWIN. Nancy already takes care of it, same way as it does on ASP.NET, so no need to worry what is underneath.
To start building some app, I need to add some client-side functionality. If I replace home.html with basic bootstrap template, and add ng-app directive to html tag, I can check if angular works:
And, as it shows ‘it works!’ in place where I have put curly brackets, I’m happy. As this is only static html, Visual Studio Page Inspector will render exactly same result as browser. Now, I’ll add application root to <base> tag, which is by default “/”, but if you ever hosted your application in IIS, and if it was not in root, but in some path (like localhost/myapp) then you know how important was to render all resources with @Url.Content helper, because all you resources would be broken otherwise. So, after I added <base href=’/’ /> and changed css and script links from relative to app-relative (removed ‘../’ prefix), I’m adding project root folder to local iis, into http://localhost/playwithowin app:
Loading project url in browser shows that OWIN works on IIS, that’s nice, but that also kills css and js resources loading, because they are loaded from root of app, which is now wrong, and it is common thing happening after you put app in virtual folder when you don’t use @Url.Content helpers. Now my angular doesn’t work properly anymore, because it tries to load it from http://localhost/Scripts/angular.js instead of http://localhost/playwithowin/Scripts/angular.js:
To fix this, I will fix path in <base> tag: <base href=”playwithowin” />
That makes everything fine again:
Next problem is, you may deploy your app to different environments, which may be on same server, in different virtual folders, or you may even want to have multiple instances of application on same server. To automate this, I’ll send base path from server:
Nancy view can accept anonymous view model, and I assign base path of request url (that is “Nancy root”) to server-side view model.
To use it in view, just use Razor-like syntax in html file! Thanks to The Super Simple View Engine, which is by default used in Nancy, it will be replaced with server variable:
So, to summarize this post, so far, using Nancy on OWIN is not different than using it on Asp.Net, and for many cases, Nancy’s Super Simple view engine is more than enough for what you need. If you still need Razor, just install NuGet: RazorEngine.
Next step in creation of app would be adding some custom js and html files. I will add angular app, one view (welcome.html), controller (WelcomeCtrl), and use them in home.html (set app name in ng-app in html tag, add div which references new view, and add references to new js files):
This is now very simple functionality, but we already have 3 referenced js files. Angular automatically loads views, but js files must be loaded explicitly, and in average application, with well separated responsibilities, there could be hundreds of js files. That could be managed using some AMD framework, but that is one of aspects where Asp.Net rules with bundling & minification, and I like it. It reduces number of requests, and we can leverage caching because it allows to automatically expire cache by varying url. In next post I will be looking on ways how to achieve same thing here.
I was keeping my eye on OWIN for some time now (since Mark Rendle’s interview in DNR in 2011, when he complained about HttpRequest and HttpResponse being sealed in ASP.Net and spoke about OWIN as alternative). I like simplicity of this interface, and I also like that Microsoft listened to community and provided Katana, their implementation of it (so now you can also run OWIN apps on IIS). OWIN got to stage where it can be used for serious applications, there is already support for multiple frameworks, some of them being Nancy, Singalr and WebAPI, so you can now build pretty much anything on top of it, and being independent from IIS and all of its http modules, handlers etc has a lot of potential to perform better (given that you don’t need all of these features that asp.net provides, which is the case for most of applications). And those of you who tried testing your code dependent on System.Web, probably already know about OWIN. For just one good reason why to use OWIN, I would just like to quote one part of that interview:
the code’s maintainability is that less code between the TCP socket and your framework. It feels naturally like that’s a good thing and it’s just less code in your application, that’s less code to go wrong. If everything is handled through interfaces or delegates, then at any point in that pipeline you can inject something in a test environment; and as far as everything beyond that point is concern, that might as well have come from a TCP socket so you can create a dictionary of headers and you don’t have to patch in everything else.
I’m big fan of clean and simple code above all, and I hate additional layers, especially when they don’t provide any valuable abstractions (don’t get me wrong, ASP.Net provides many useful abstractions, and it is great framework, but sometimes there is just no need for all of that), sometimes you just don’t need all that infrastructure, actually I would say that most of applications don’t need it, especially today when more and more applications are running in browser, you just need as simple way as possible for your application to communicate to server.
So, as I always want to learn something and extend my skill set, I choose to put OWIN under my belt, as creating HTTP services which can be self-hosted (or in windows service, or in exe/scheduled task, or…) can come in pretty handy.
To get started with OWIN, I’m using Visual Studio 2013, it takes few simple steps:
This gives you choose template screen:
That gives new project that is (aside from plenty references) empty, it contains only web.config.
If you are not using Resharper, then you should :), but for this matter you can use some other extension to clean up unused references, that will leave your project with only System and System.Core. To get started with Nancy and Owin, use NuGet PM Console: Install-Package Nancy.Owin. That will also pull Nancy, as dependency. That puts Nancy, Owin, and Nancy.Owin into references. After that, project looks like this:
To run app, you need to host it somewhere. As most convenient way to develop is to run it from Visual Studio, it is necessary to add hosting adapter to host OWIN in IIS (or Express version that is used by Visual Studio):
This adds Microsoft implementation of Open Web Interface (aka Project Katana) and hosting adapter which contains OwinHttpHandler used to handle http requests and pass them to OWIN. These are in Microsoft.Owin, and Microsoft.Owin.Host.SystemWeb libraries, respectfully.
After these few steps, it is possible to run this frame for application:
As this is not MVC application from VS template, this is expected, but it is very nice and descriptive exception, and it makes clear what is next step to do to get it working: it is necessary to either add OwinStartup attribute to assembly, or to create Startup class with Configuration method. As “Startup.Configuration” sounds explanatory, I will do that:
Configuration method’s signature is documented in Katana documentation, but you don’t even have to open it, if you don’t make it like this, another exception will tell you to do it. This part is actually what is this whole post about. This single line of code in Configuration method is actually all you need to do to run Nancy on OWIN.
It is worth noting that IAppBuilder is not official part of OWIN interface, but part of Katana itself, and if you decide to run your app on something else, then it may be necessary to change way how application starts.
UseNancy extension method comes from Nancy.Owin package, and it is just wrapper around builder.Use:
If you take a look into NancyOwinHost, you will see that it is just an adapter to Owin infrastructure, similar to NancyHandler for Asp.Net, but difference is that handler gets to work with HttpContextBase (which is abstract, and not very simple to mock/fake), while NancyOwinHost gets Dictionary<string,object> which is how http request is represented in Owin. It is lower level of abstraction, meaning it is much closer to the metal, and if you don’t need all of the fancy stuff in HttpContext, then it is likely that this is going to perform better, with less resources.
Running application now gives default Nancy 404 response:
Ok, Nancy gets request, and as there is nothing to process it, returns not found.
To return something useful to client, we need a “controller”. In Nancy, that is Module:
This is how handler for get request for root path (“/”) is defined in Nancy. I like it, as to me is much more expressive than “Index” ActionResult.
As I’m returning view named “home”, I will create it in “Views” folder (standard convention, Nancy will look for it there):
And result is:
So, our web site in .NET without System.Web is live:
This is yet far away from being an application, but building one using Nancy and Owin is not so much different than using MVC and Asp.Net. It is always useful to learn other ways to do same thing, because that gives you another perspective and ability to see things you missed before.
I end this post here, and next step will be more about Nancy, and how to add some script and css resources and see how to serve them to browser, and what is different in OWIN than in Asp.Net, as standard bundling libraries reside on top of System.Web and won’t work here.
I pushed source code for playwithowin project to github. You will have to restore NuGet packages as only code is there, so don’t go offline until you build it once 🙂