Saturday, February 28, 2015

Nancy 1.0 and the Book

In light of Nancy recently reaching 1.0 (and quickly thereafter 1.1), I thought it was appropriate to revisit my Nancy book, and the running code sample in it on Nancy 1.1. This post looks at what's changed and what I might have coded differently now.

But first,

Is the Book still Relevant?

Yes, I think the book is still relevant. Almost all the code works unchanged with Nancy 1.1, and Nancy still follows the same principals and philosophy. I still think the book is a quick way to get introduced to Nancys way of doing things, the DSLs it provides and it awesome extensibility.
(But then again, I may be slightly biased)

What Broke Between Then and Now?

After updating the Nancy packages in my copy of the code for the 12th and final chapter of the book only one thing did not compile. One method on the IBodyDeserializer interface has changes, namely CanDeserialize which now receives a BindingContext as an argument. I added this argument, compiled and all tests passed and AFAICT everything worked.
That's it. And that says a lot about Nancy. There may not be a lot of promises of backward compatibility, but still the effort needed to update from 0.17 to 1.1 was minimal.

I have had comments that the MongoDB driver used is out of date and that the code in the book uses methods from it that are now obsolete. Since MongoDB is not the subject of the book and the code still works, I'm going to continue punting on that one, and just say no big deal.

What Would I Have Done Differently?


Hosting

The book covers ASP.NET hosting and self hosting and how to setup a solution where the site is in a class library which can be re-used across hosts. Today I might still start out with the ASP.NET host because it is familiar to many ASP.NET developers, but self hosting as well as the cross host scenario would be OWIN based. In general I'd recommend OWIN hosting now, so that would have some space in the book, if written today.

The Cloud Chapter

Hmmm. Deploying Nancy to the cloud. That chapter seemed like a good idea up front. But wasn't. It ended up being more about some esotric xUnit setup stuff than about deployment. Why? Because deploying Nancy to the cloud is no big deal. It's just like deploying any ASP.NET (or OWIN) application to the cloud. In other words nothing special.
I didn't see that while writing, though, but I hope I would have left this chapter out if I'd written the book today. Maybe a chapter on OWIN would have been a better idea.


Authentication

The book describes adding Tiwtter login using the Worlddomination NuGet packages. Unfortunately that package changed it's name to SimpleAuthentication between my final draft and the publication of the book. Grrrrrrrrrrrrrrrrrrrr.
In any case, if writing the book today I think I would have pushed the Twitter authentication down to the OWIN level. On the other hand that would mean less focus on Nancy and more on OWIN. But I think that is what I'd do, because using OWIN middleware for authentication would be my (general) recommendation today.

Test Defaults

I worte the book in a test first fashion - showing tests first and then implementation. I'm still happy with that decision, because it emphasizes the awesome Nancy.Testing library and just how testable Nancy is. -And for me testability is a major feature of a framework.
There is a feature that has been introduced in Nancy since the book was written that would have allowed me to cut down on a lot of duplication in the test code, namely defaults for the Browser object. I would have used that all over the book if writing it now, and highly recommend using the Browser defaults.

Logging

This is minor, but if writing the book today I would not have used NLog but SeriLog instead.

Friday, February 6, 2015

Why Write (OWIN) 'Middleware' in Web Applications?

TL;DR

Middleware - in the OWIN sense - can help you modularize your web application code, and maybe even enable you to reuse the plumbing code needed to deal with cross cutting concerns.

What is Middleware?

The context of this post is web applications, and in that context middlewares are pieces of code between the web server and the application code:


When a request comes in it is first handled by the web server, which hands it off to the first piece of middleware, which hands it to the next and so on until the request reaches the application code - i.e. the Nancy Modules or MVC/WebAPI controllers. The response takes the opposite route from the application, through the middlewares and the web server. You can think of that as a pipeline. The pipeline starts and ends with the web server, has the middlewares along the way and the application in the middle:


The trick here is that the middlewares all conform to the same interface; meaning that the pipeline be composed in many different ways - we may omit middleware 3, insert a 4th between 1 and 2 or swap 2 and 3.


Put Cross Cutting Concerns In Middleware

When we look at the handling of an HTTP request as a pipeline there are some things that we can immediately see that we could stick into that pipeline and thereby have applied to all requests. The obvious examples are request and response logging, perfomance logging and authentication. Indeed these are things that there are OSS OWIN middleware implementations for.
Slightly less obvious maybe are the more application specific things like request throttling, caching, redirects of obsoleted URLs, or even things like integration to a payment gateway.
The common theme of these candidates for middleware is they are moving concerns that should otheriwse have been handled by the application code out into the pipeline. This not only cleans up application code but also lends you the flexibility of the pipeline to re-configure the cross cutting stuff in one pipeline across all end points.


Middleware in a Service Oriented Architecture

I'm usually wary of the promise of reuse, but it does depend on where the reuse happens. There is usually not a whole lot of reuse of business logic between applications. But the frameworks they are built on are hugely reused. Middleware sits (well) in the middle.
In the case of service oriented architecture (where HTTP is use for inter-service communication) serving one or more applications there is a potential for reuse across services of the types of plumbing that are specific to this particular architecture but not to each individual service. Things like

  • adding monitoring endpoints to each service (middleware can short circuit the pipeline such that requests never reach the application)
  • collecting usage data
  • opening and closing database sessions
  • keeping track of correlation tokens
  • caching rules
  • ...

These are all examples of things that you don't want to write for every single service, but that you might want every service to have. The more services there are and the smaller each one is the more important the reuse of plumbing becomes. Wrapping each of these cross cutting pieces of functionality into middleware which plugs right into the pipeline makes them readily reusable across services.

OWIN and ASP.NET 5

Both OWIN and ASP.NET 5 supports the idea of middleware. In OWIN it's one the central features. In ASP.NET 5 the same feature is available 1) because ASP.NET 5 supports OWIN and 2) because it also brings it's own notion of middleware to the table.

In future post I'll dig more into both OWIN middleware and the 'proprietary' ASP.NET 5 middleware.