One day I was reading an article about Amazon and how every product/service or tool is required to be behind a REST api. Being a .NET developer I was curious if there was a way I could utilize Kestrel and MVC just in a console app to create a simple REST API that could possibly run in a Docker container or just as a simple standalone app on a server for testing.
Turns out this is a fairly simple processes but as it does not appear to be very common use case the documentation is a bit cumbersome to get through. So below are the simple steps that I took to stand up my own REST API using Kestrel and MVC.
First create a new Console APP, I’ll be targeting .NET 5
From Command Line
C:\Users\> dotnet new console -o "e:\testconsole" -n KestrelTest -f net5.0
Command above does the following – create a new application using the console template, output the contents to the E:\testconsole directory and call the project KestrelTest and target the .net5.0 framework.
Before we open up the app in VS lets add the two packages that we will need from nuget.
From command prompt go to your projects directory and execute the following commands:
dotnet add KestrelTest.csproj package Microsoft.AspNetCore.Server.Kestrel --version 2.2.0
dotnet add KestrelTest.csproj package Microsoft.AspNetCore.Mvc --version 2.2.0
We are going to be making use of the WebHostBuilder object and calling the .UseKestrel() method that it exposes. However, before we can actually start up the web host we need to create a Startup class. This class is named by convention and has two methods that you will see below that are called by the runtime when the app starts.
This is what the current solution looks like:
You can add the Startup.cs file to the root of the project, the class will need to have the following signature.
You need a constructor that takes a IConfiguration object, and two methods Configure which takes a IApplicaitonBuilder and ConfigureServices which takes IServiceCollection.
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
namespace KestrelTest
{
public class Startup
{
public IConfiguration Configuration { get; }
public Startup(IConfiguration configuration)
{
this.Configuration = configuration;
}
public void Configure(IApplicationBuilder app)
{
}
public void ConfigureServices(IServiceCollection services)
{
}
}
}
Now lets add some configuration to the Startup.cs file
For this simple app we are only going to be making use of MVC and a default route.
lets add that configuration
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
namespace KestrelTest
{
public class Startup
{
public IConfiguration Configuration { get; }
public Startup(IConfiguration configuration)
{
this.Configuration = configuration;
}
public void Configure(IApplicationBuilder app)
{
app.UseMvc((routebuilder) =>
{
routebuilder.MapRoute(
name: "default",
template: "{controller}/{action}"
);
});
}
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddRouting();
}
}
}
Okay so we added MVC so we can utilize controllers and we added routing.
From this point on there will be some presumed understanding of how MVC controller and routing works, but if you are completely new to that world then it may seem a bit magical at first. At least that is how I felt when I first started out.
Now lets configure a controller, our controller is just going to return a simple Book object for now. The Mvc framework will convert the Book object into json when its returned to the caller.
using Microsoft.AspNetCore.Mvc;
namespace KestrelTest
{
public class BookController : Controller
{
public Book GetBook()
{
return new Book()
{
Title = "Tale of Two Cities",
Author = "Charles Dickens",
PageCount = 262
};
}
}
public class Book
{
public string Title { get; set; }
public string Author { get; set; }
public int PageCount { get; set; }
}
}
Okay now that we have our controller lets configure and build our web host.
Back in the main method of the Program.cs file add the following.
using Microsoft.AspNetCore.Hosting;
using System;
namespace KestrelTest
{
class Program
{
static void Main(string[] args)
{
var host = new WebHostBuilder().UseKestrel().UseStartup<Startup>().UseUrls("http://localhost:4545", "https://localhost:4546").Build();
//calling host.Run() like this will block the main thread untill the app is stopped.
host.Run();
}
}
}
At line 10, you can see that we telling the HostBuilder to use Kestrel, we are then telling kestrel what type to use for the startup in this case its Startup so its a bit confusing, I simply went with convention you could call the Startup object anything you want. Then we are specifying what urls to use and calling build, which will give us a fully configured host.
Then we call host.Run() which will block the main tread and prevent the app from closing.
Now that we have all the classes and files created our app should look like this.
But for the true test, does it run and can we hit our endpoint and get something back, if we cant do that then its pretty pointless to have it.
App starts and is listening on the ports that we specified in the UseUrls method…good so far but can we get data back???
All right looks like its working. Now this was just a simple demonstration and that is kind of the point, it is this easy to standup a REST API utilizing the very powerful features that Mvc has already. You could even adapt this to run in a docker container as is. That is what I will be coving in my next post.
Note on routing, you can see from the curl command that I requested data from the /Book/GetBook location this corresponds to how we setup the default route template, “{controller}/{action}” in the case above our controller is called BookController but MVC strips off the Controller part and it is referenced just by Book and the Action or in this case the method that we are calling is GetBook. This is a very simplified routing example as it can get much more complicated.