.Net Core and NancyFX: can writing a WebApi get any simpler?
Categories:
3 minute read
Last Thursday I attended a Meetup hosted by my friends of @MsCodersMadrid in Madrid where, thanks to @snavarropino, I learned a bit about the NancyFX open source framework.
I really couldn’t believe my eyes when I saw how simple it is to use NancyFX to write a Web API. Two of the things that got my attention were: the out of the box content negotiation and zero configuration dependency injection.
What are we waiting for? Lets’s put in the mix .Net Core and NancyFX and ask ourselves: can a WebApi get any simpler?.
Steps:
Create the application
Open a command prompt and run
md nancyfx.sample
cd nancyfx.sample
dotnet new
dotnet restore
code .
Replace the contents of project.json
Replace the contents on project.json file. Be sure to include the references to Microsoft.AspNetCore.Owin and Nancy
{
"dependencies": {
"Microsoft.NETCore.App": {
"version": "1.1.0-preview1-001153-00",
"type": "platform"
},
"Microsoft.AspNetCore.Server.IISIntegration": "1.0.0",
"Microsoft.AspNetCore.Server.Kestrel": "1.0.1",
"Microsoft.AspNetCore.Owin": "1.0.0",
"Nancy": "2.0.0-clinteastwood"
},
"tools": {},
"frameworks": {
"netcoreapp1.1": {
"imports": [
"dotnet5.6",
"dnxcore50",
"portable-net45+win8"
]
}
},
"buildOptions": {
"debugType": "portable",
"emitEntryPoint": true,
"preserveCompilationContext": true
},
"runtimeOptions": {
"configProperties": {
"System.GC.Server": true
}
},
"publishOptions": {},
"scripts": {},
"tooling": {
"defaultNamespace": "WebApplication"
}
}
Replace the contents of Program.cs
Let’s host the Web API with AspNetCore
using System.IO;
using Microsoft.AspNetCore.Hosting;
namespace WebApplication
{
public class Program
{
public static void Main(string[] args)
{
var host = new WebHostBuilder()
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseStartup<Startup>()
.Build();
host.Run();
}
}
}
Add a Startup.cs
This one-liner hooks NancyFX to our application.
using Microsoft.AspNetCore.Builder;
using Nancy.Owin;
namespace WebApplication
{
public class Startup
{
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app)
{
app.UseOwin(x => x.UseNancy());
}
}
}
Create a service to return some random message
Add a new file (i.e BaconIpsumService.cs) to hold the application logic and add the following sample content
using System.Net.Http;
using System.Threading.Tasks;
namespace WebApplication
{
public class BaconIpsumMessage
{
public string Body {get; set;}
}
public interface IBaconIpsumService
{
Task<BaconIpsumMessage> GenerateAsync();
}
public class BaconIpsumService : IBaconIpsumService
{
public async Task<BaconIpsumMessage> GenerateAsync()
{
using (var client = new HttpClient())
{
var message = new BaconIpsumMessage();
// Post the message
message.Body = await client.GetStringAsync(
$"https://baconipsum.com/api/?type=meat-and-filler");
return message;
}
}
}
}
Create a NancyFX module to host the WebAPI
Create a new file (i.e BaconIpsumModule .cs) to hold the routes and actions for the Web API
using Nancy;
namespace WebApplication
{
public class BaconIpsumModule : NancyModule
{
public BaconIpsumModule(IBaconIpsumService baconIpsumService)
{
Get("/", args => "Super Duper Happy Path running on .NET Core");
Get("/baconipsum", async args => await baconIpsumService.GenerateAsync());
}
}
}
The first route returns a string and the second one calls our service and returns a BaconIpsumMessage instance (And yes! NancyFX supports async too!).
Also note that the module requires an instance of IBaconIpsumService in the constructor but don’t worry because NancyFX will inject it for you without any special configuration or registration!
Run and test the application
Run the following commands
dotnet restore
dotnet run
Navigate to http://localhost:5000 and the browser should show the message: Super Duper Happy Path running on .NET Core
Navigate to http://localhost:5000/baconipsum and because of automatic content navigation NancyFX will try to find a view to display the BaconIpsumMessage which we didn’t register and therefore results in an internal server error:
Now call the same url: http://localhost:5000/baconipsum using postman and you’ll get the expected json:
Get a copy of the code here: https://github.com/cmendible/dotnetcore.samples/tree/main/nancyfx.sample
Hope it helps!