Trying Out NancyFx

As part of not doing very much coding lately, I have decided that I am going to try to spend more time trying out new frameworks and technologies. And hopefully, that will en up with a lot more blog posts with interesting stuff. This time I have looked at a ridiculously funky micro framework for building HTTP-based services called NancyFx. It is really simple to get started with, but still very powerful…and modern…

Nancy can be hosted in a variety of ways, including in ASP.NET MVC, WCF and self-hosting. In this post, I will look at hosting Nancy in a console application as I had little interest in setting up anything big. And using NuGet, it was a piece of cake to get started. Just start up a new Console application project and then NuGet Nancy.Hosting.Self.

Once we got Nancy NuGot (new word?), we can get started hosting it. it requires 2 lines of code, but I will use 4 as I need some stuff to handle the fact that I am in a console app…

var host = new Nancy.Hosting.Self.NancyHost(new Uri("http://www.nancytesting.org/"));
host.Start();
Console.ReadKey();
host.Stop();

As you can see from the code, I just create a new NancyHost, telling it what Uri to use, and then start the host. In this case, I have tweaked my hosts file to have www.nancytesting.org point at 127.0.0.1…

Next, it is time to have Nancy do something for us, which is also ridiculously simple. Nancy will automatically discover any “module” in the application, and register it for use. So let’s create a simple module by creating a class that inherits from Nancy.NancyModule. As I am going to demo Nancy, I named my module DemoModule, but you can of course use whatever name comes to mind…

public class DemoModule : NancyModule
{
}

That’s it! Of course, it doesn’t actually do anything yet, but that comes later. All I wanted was a module, which I know have…

The way that a NancyModule works, is that it basically exposes a dictionary for each of the HTTP verbs. The dictionary takes a string that identifies the path to respond to, and a Func<> to handle the request. The path string can be a specific path, a path with parameters defined or even a regular expression.

The simplest possible way to start using Nancy would be to add the following constructor

public DemoModule()
{
Get["/"] = parameters => "Hello World";
}

This will make sure that Nancy responds to “/” by passing back a string saying “Hello World”.

Now, if we press F5 to start the console app, and then browse to the Url defined when starting the Host, we should see “Hello World” being presented in the window…

The parameters parameter that is passed to the Func<> is a dynamic object containing all the values being parsed from the path. That might be a bit hard to grasp by that description, so let’s try it out by adding a new route containing a parameter

public DemoModule()
{
Get["/"] = parameters => "Hello World";
Get["/echo/{value}"] = parameters => parameters.value;
}

As you can see, the new route contains a parameter as part of the path, which is defined by using {parameter name}. That parameter is then available through the dynamic object being passed to the Func<>. So sending a request to /echo/chris would return “chris”.

If you want to, you can also add a “condition” to the route registration. That is you can add a Func<> that gets called to evaluate whether or not the route should be used. This can be a very powerful way to filter routes with logic… Something really contrived would be something like this

public DemoModule()
{
Get["/", ctx => DateTime.Now.Hour < 8 || DateTime.Now.Hour > 17] = parameters => "Sorry, we are only open during business hours";
Get["/"] = parameters => "Hello World";
}

Just remember that the order that the routes are registered in this case is obviously important…

Nancy also supports using views, in much the same way you do in ASP.NET MVC for example. It supports several view engines, including the lovely Razor one, but comes bundled with a view engine known as the SuperSimpleViewEngine. It looks a whole lot like Razor, but isn’t quite as powerful…

To return a view, just create a folder called “views” and add a new text file with the extension sshtml. You can also put the view in the root of you would prefer that. Just remember to set the “Copy to Output Directory” to “Copy always” or “Copy id newer”… Then put whatever markup you want in the view, and have your route return View["View.sshtml"]

public DemoModule()
{
...
Get["/view"] = parameters => View["MyView.sshtml"];
}

And as with any MVC framework, you can of course pass a model to the view and have it render based on that. The way to do this, is to use the @Model key in the view, just as with Razor. However, the @Model in the SuperSimpleViewEngine is a dynamic object, so you have to define a property that you whish to output, for example @Model.Name.

<html>
<head>
<title>Hello @Model.Name</title>
</head>
<body>
Hello @Model.Name
</body>
</html>

Next, you have to create a route that creates a model object to pass to the view. Like this

public DemoModule()
{
...
Get["/hello/{name}"] = parameters => View["HelloView.sshtml", new { Name = parameters.name }];

Ok…that is the basics of using NancyFx. The last thing I want to show is the fact that the module has access to a couple of very powerful properties.

The first one is the BeforePipeline, which is a place for you to hook into every single request before they are executed. Just as you would do in an HttpModule or in the Global.asax in ASP.NET. It also has a corresponding AfterPipeline. They are available as the properties Before and After.

The second one I want to mention is the Context property, which is of type NancyContext. This context gives you access to all the things you need regarding the current request.

Using these properties, we could easily put logging into the module like this

public AcsModule()
{
...
Before += ctx =>
{
Debug.WriteLine("Executing request {0}", ctx.Request.Url);
return null;
};
After += ctx => Debug.WriteLine("Executed request {0}", ctx.Request.Url);
}

As you can see, the Before handler returns null. It can also return a Nancy.Response object, and thus cause the request to stop in the pipeline and never carry on to the actual route, which can be very powerful. Just remember that you still need to have a valid route for the request to come in…

Oh…yeah….one last thing before I carry on with the ACS stuff… Nancy has no reliance on System.Web. It even runs in Client Profile. So the request and response objects, and even the HttpUtility object, are all Nancy specific, which can cause some minor issues when working with things that expects an HttpRequest object for example…

That’s it for this time. Short and simple! And the code is obviously available here: NancyDemo.zip (964.76 kb)

Just remember that you need to run VS as administrator as Nancy opens ports…

Pingbacks and trackbacks (1)+

Add comment