Nancy

Hello all,
I’m hoping everyone has had a good week. Tis Thursday folks, the weekend’s a’comin’!
I also realized that I barely blog about anything C#, which is a shame since the blog’s tagline implies I should, so this week I’m going to talk about Nancy. I’ll take a rain check on the Alchemy thing though…
NancyFx or Nancy for short is a lightweight, server-side web framework for the .NET framework. Basically, it comes into play when you’re trying to build a web-application with server-side smarts, such as a data-bound application (where data is stored, queried and retrieved), building web APIs (web apps returning XML or JSON data in response to requests) and things like that. Granted, there are tons of neat frameworks to do this for every language – there’s Django for Python, there’s ASP.NET and ASP.NET MVC for the dotNet framework itself, etc. However, ASP.NET and ASP.NET MVC are rather heavy and (for me) rather difficult and clunky to deploy on non-Windows hosts. If you’re going to use any of them, you get a ton of things you might not really need, and that’s when you get it to work. Getting them to work on Mono can be quite a pain in the neck, although I’m told ASP.NET Core aims to fix some of these issues..until then however.
Enter NancyFx.
Essentially, NancyFx makes it easy to build server-side apps (I said this before) but without the gunk/overhead of ASP.NET, and most importantly, makes hosting said server-side apps a cinch – so whether you’re deploying on Windows or whatever you have options that are largely painless to use. Basically, NancyFx gives you considerably more flexibility when building server-side web apps, from the deployment methods available to the other components used, normally allowing you swap out things like View Engines easily.
Earlier this week, I found myself trying to host a simple web app on a Raspberry Pi. Normally I’d use a small framework I’d developed a while ago to do this, but a couple of people had told me about Nancy so I figured this was as good a time as any to get my hands dirty. So I visited the NancyFx homepage, and followed the instructions on there to get started. Essentially I wanted to host the app within a console application which would be invoked by Mono, so I used NancyFx’s self-hosting feature which permits me to do just that. First off, you install the NancyFx package (and the Nancy.Hosting.Self package too, for self-hosting) into your source/working directory from Nuget. Next, write code to use the self-hosting feature. This essentially involves adding a using directive for the Nancy.Hosting.Self namespace, then creating a NancyHost instance in code, specifying your listener URL and port, and starting the instance. Something like this:
Nancy_Hosting
On Windows you’ll need to edit your URL ACL accordingly, or the app will fail to start. There’s some info about that on the Nancy Wiki, but I’m too lazy to look it up Smile with tongue out
To actually define routes and their handlers, you create other classes and inherit from NancyModule. So for example, stealing this from the NancyFx homepage:
Nancy_Sample
This essentially means that a GET request made to the root path (“/”) of the application returns the string “Hello World!”. Easy as that. Technically, the route handlers themselves are simply generic Func instances (we’ll talk about this later). For a POST request, the code would be:
Post[“/”] = … //some code here
There’s no explicit configuration needed – at runtime, NancyFx automatically locates any classes that inherit from NancyModule in your application and registers them to handle these routes all in the background. This is part of their Super Duper Happy Path (SDHP) paradigm – simple and elegant. When a request comes, Nancy will instantiate the relevant class and invoke the route handler matching the URL for that request.
Normally, you’d want to use a bit of the MVC pattern, so you can consider your NancyModule-inherited class to be your controller, your data models as your model classes, and the resulting webpage as your view. As with normal MVC, Nancy lets you insert a model right into a View, and provides the really cool Super Simple View Engine (SSVE) out of the box. Say for example, my model class…models…maybe a car, so it looks something like this:
Car_Class
And I’m trying to display the this model in a webpage. I can inject the model into the view as follows:
Car_Request
[For now, ignore the /car/{id} and parameters bits. I’ll get to that shortly.]
And within the HTML itself (inside a page called Cars.html), add the following SSVE directives to access the model object:
Car_SSVE
If you’re already familiar with ASP.NET’s Razor (Engine) syntax, then you’ll immediately notice the similarities – rather than @model which ASP.NET uses, Nancy’s SSVE uses @Model to refer to the injected model object. The SSVE isn’t quite as fully featured as Razor. For instance, it does not have support for the @ViewBag which Razor does. Nancy also supports ASP.NET’s Razor View Engine, if the SSVE doesn’t cut it for you. To use it, you’ll simply need to install the Nancy.ViewEngines.Razor package from Nuget, and voila! It seems like Nancy is plugin-based, so whenever you want some particular functionality, you simply install the relevant package and you get it. This let you mix and match components as you see fit, which I personally think is great.
From the Nancy snippet above (the picture above the HTML snippet) you’ll notice that Nancy gives you super simple routing constraints (if that’s the right term). From above, the request handler is only executed if the request looks something like: domain.com/?id=n (where n is the requested id). If the requesting URL doesn’t have the Id value in the query string, Nancy considers that to be a different route entirely and will search out a matching handler. This is similar to parameterized Actions in ASP.NET MVC. In fact, the id value can be specified as being an integer by replacing the route constraint with: “/car/{id:int}”, which tells Nancy that the Id value in the query string must be an integer before the route handler will be invoked.
The parameters argument (visible in the previous code example) is a dynamic dictionary which contains each of the query variables as keys and the resulting query variable values as the corresponding values. Remember I mentioned that route handlers are simply generic Func instances? Well, they take two types. The first type is dynamic, and is created and populated from the data included in the incoming request itself. The second is the return type and is some internal interface in Nancy (which we frankly don’t need to worry about – simply return an integer return code, a string, a webpage, etc and Nancy will handle it for you). In the first “Hello World” example up above, we didn’t need any request variables so we replaced the argument name (for the first Type) with “_”. However, when you’re interested in them, simply give the argument a name. Like “parameters” (which we have done here). As such, parameters will be the name of the instance of the first Type (the dynamic) passed in. For instance, if the request is: domain.com/?id=1&color=red, the parameters object will then have two properties: parameters.id, and parameters.color. Accessing them will yield 1 and “red” respectively. Regular dictionary syntax can also be used i.e these properties could be accessed as parameters[“id”] and parameters[“color”] as well.
There are tons of things and options to Nancy, so rather than repeating all of that information here take the red pill and head over to the NancyFx homepage.
See just how deep the rabbit hole goes.

Comments

Popular posts from this blog

Bitbanging SPI on the Raspberry Pi (via spi-gpio)

Enabling SPI1 on the Raspberry Pi B+/Zero/2/3

Getting Started with Logic Analyzers and Pulseview