Nancy on OWIN – serving static resources

For this post, I’m using same playwithowing project I created during last blog post, which is on github.

First thing that I want to do, is add some NuGets:

PM> Install-Package bootstrap
PM> Install-Package angularjs

These two are enough for now, I have both css and javascript files that I need on client now.

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 nothing needed 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.
As this works, now you can start programming 🙂 There is one thing that is from my experience very neglected and many developers don’t know or don’t use it, and that is <base> html tag. It is very useful, especially if you want to create Single-Page or Rich-Client applications, which tend to load lot of resources from JavaScript and don’t have access to Html helpers like Url.Content or Url.Action that you can see all over the place in views in Asp.Net MVC.
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:
Testing angular in page inspector
Testing angular in page inspector

 

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:

 

 

Nice thing about <base> tag is that doesn’t only fix these urls, but as we will see, also removes need to have ‘root’, ‘approot’ or whatever is the name that you use in global javascript namespace to inject that path in master/layout page and to make js code aware of it for needs of loading any static resources asynchronously. For me that was always one of ugliest things in JavaScript, and now you can just forget about it. Just use apprelative paths in your app, and point base tag to your app root, whatever is it.

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:

 

Screenshot 2014-04-13-18-56-17-6571639
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):

app files and result

 

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.

Source code for this version is pushed to github.