Hello ladies and gentlemen. It was thought, in our Friday heading there was not a single article about inflatable dinosaurs in the context of the hotel business.
If suddenly you are not at all interested in the NancyFX framework and microservices on the .NET platform, created with its help - read about dinosaurs!
Our office is not to be confused with anything - we have inflatable dinosaurs installed here, a whole park of viewable monitors, and the whole team is constantly chasing Yorkshire teas. But in order to devote the time that he undoubtedly deserves to such a life-giving style, we must quickly and efficiently solve our basic tasks - in particular, maintain a service with which our customers can book hotel rooms.
To make it even better, we gradually redesigned our code base segment for
microservice architecture . First, we wrote the API Reservations API, highlighting all the functionality associated with creating and retrieving booking records into a separate domain with independent versioning, releases and maintenance systems. So we were able to easily support new cross-platform front-ends - for example, the mobile version and the form of a reservation based on Node.js
')
But then we went further and singled out such stages of the reservation (for example, sending confirmation messages), which do not necessarily have to be carried out strictly before the confirmation is returned to the frontend. The booking process itself can be reduced to two sets of actions: ordering a room in a hotel and keeping a corresponding record if we can be sure that after this both operations will be carried out as quickly as possible. To do this, we added message queues to our toolkit and used a set of command and event processors designed to handle such out-of-band tasks.
Soon we needed a set of services, each of which was responsible for a specific part of the domain. In order to develop them, we needed to quickly and easily write a REST API, preferably without slipping. That's when we found Nancy.
NancyFx is a terrific easy web framework for .NET. If you are targeting frameworks for other languages, for example, Sinatra and Express, then you can quite well imagine what to expect from it. On the other hand, if you are familiar only with such .NET-blocks as Microsoft MVC and WCF, then, quite possibly, you will have a pleasant surprise.
Instead of singing the praises of Nancy (I can do it for hours), I’ll better show you how much easier it is for a simple turnip to write a simple REST-style endpoint in Nancy in less than 15 minutes.
Step 1: Create a C # Console Application
Of course, this can be done in another language for the .NET platform. Even on VB.
Step 2: Import Nancy
Nancy is provided in the form of Nuget packages, so I recommend using the Visual Studio package manager - the most convenient tool for importing binary files into a project and links to them. In this case, we need the
Nancy.Hosting.Self
package, depending on the main Nancy package.
Step 3: Create a Nancy Host
In the
Main
method (or the equivalent entry point of the program) write:
using (var host = new NancyHost(new Uri("http://localhost:1234")) { Console.ReadKey(); }
You have already created a console application that listens for HTTP on port 1234. In fact, we like to do this, it is a simple implementation of reverse proxies that send external HTTP requests to a managed process. However, Nancy also supports OWIN, traditional IIS hosting.
Step 4: Create a route to the resource
We create our first route, inheriting the
Module
class from Nancy. Write this in a file with a new project:
class Dinosaur { public string Name { get; set; } public int HeightInFeet { get; set; } public string Status { get; set; } } class DinosaurModule : NancyModule { private static Dinosaur dinosaur = new Dinosaur() { Name = "Kierkegaard", HeightInFeet = 0, Status = "Deflated" }; public DinosaurModule() { Get["/dinosaur"] = parameters => dinosaur; } }
When you start a host, Nancy looks at your assembly and looks for classes in it that inherit from
NancyModule
. They will be instantiated whenever a request arrives, provide routing and action. In this case, we create a simple GET route in the module's constructor and use the lambda expression, with which we return the object of the model we defined. If you call
localhost : 1234 / dinosaur without a title with the type of content, then the dinosaur model will come to us in JSON format. Run the application, try it.
Step 5: Add a write operation
Until now, our resource was read only. Add the following code to the
DinosaurModule
constructor:
Post["/dinosaur"] = parameters => { var model = this.Bind<Dinosaur>(); dinosaur = model; return model; };
The binding accepts the body of the HTTP request and tries to associate it with the specified type of model. Try to send the following code to
localhost : 1234 / dinosaur, content type - application / json:
{ "name": "Kierkegaard", "heightInFeet": 6, "status": "Inflated" }
The request body should be tied to the
Dinosaur
class and assigned to our static member
Dinosaur
. As with the
Get
endpoint, we return the model, after which Nancy serializes the JSON model. Nancy has features like content discussion and view rendering, but in this demo, the default behavior is fine.
Step 6: Create and Return Indexed Resources
As a rule, when we write REST API, we need several from each resource. Let's modify the class a bit:
public class DinosaurModule : NancyModule { private static List<Dinosaur> dinosaurs = new List<Dinosaur>() { new Dinosaur() { Name = "Kierkegaard", HeightInFeet = 6, Status = "Inflated" } }; public DinosaurModule() { Get["/dinosaurs/{id}"] = parameters => dinosaurs[parameters.id - 1]; Post["/dinosaurs"] = parameters => { var model = this.Bind<Dinosaur>(); dinosaurs.Add(model); return dinosaurs.Count.ToString(); }; } }
Now the route is
/dinosaurs
. The
parameters
object in a lambda expression is essentially a dynamic type that combines values from a route, a query string, and a request body. By defining the
{id}
parameter within the route, you can capture it, and then use it to extract the resource we need.
On the sending route, you can continue to post dinosaurs and add them to the collection. In this demo, we simply return the index of the created resource as a string in the response body. You may prefer to return the navigation link to a fresh resource so that the user can easily access it.
Step 7: Your turn
In the final of our very sightseeing tour, we had such a Spartan end-REST point. What's next? Naturally, we want to keep our resources in some kind of long-term data storage, not in memory, but what about validation, error handling, security?
With all the ease and simplicity of Nancy, right out of the box solves many such questions, and also provides other features that you can easily incorporate into the project.
So, you made a general idea about Nancy - and now read the
documentation .