The .NET Stacks #29: More on route-to-code and some Kubernetes news

This week, we dig deep on route-to-code and discuss some Kubernetes news.

Dave Brock
Dave Brock

Note: This is the published version of my free, weekly newsletter, The .NET Stacks. It was originally sent to subscribers on December 7, 2020. Subscribe at the bottom of this post to get the content right away!

Happy Monday! Here’s what we’re talking about this week:

  • Digging deeper on “route-to-code”
  • Kubernetes is deprecating Docker … what?
  • Last week in the .NET world

🔭 Digging deeper on “route-to-code”

Last week, I talked about the future of writing APIs for ASP.NET Core MVC. The gist: there’s a new initiative (Project Houdini) coming to move MVC productivity features to the core of the stack, and part of that is generating imperative APIs for you at compile time using source generation.

This leverages a way to write slim APIs in ASP.NET Core without the bloat of the MVC framework: it’s called “route-to-code.” We talked about it in early October. I thought it’d be fun to migrate a simple MVC CRUD API to this model, and I wrote about it this week.

As I wrote, this isn’t meant to be an MVC replacement, but a solution for simple JSON APIs. It does not support model binding or validation, content negotiation, or dependency injection from constructors. Most times, though, you’re wanting to separate business logic from your execution context—it’s definitely worth a look.

Here’s me using an in-memory Entity Framework Core database to get some bands:

endpoints.MapGet("/bands", async context =>
{
    var repository = context.RequestServices.GetService<SampleContext>();
    var bands = repository.Bands.ToListAsync();
    await context.Response.WriteAsJsonAsync(bands);
});

There’s no framework here, so instead of using DI to access my EF context, I get a service through the HttpContext. Then, I can use helper methods that let me read from and write to my pipe. Pretty slick.

Here’s me getting a record by ID:

endpoints.MapGet("/bands/{id}", async context =>
{
    var repository = context.RequestServices.GetService<SampleContext>();
    var id = context.Request.RouteValues["id"];
    var band = await repository.Bands.FindAsync(Convert.ToInt32(id));

    if (band is null)
    {
        context.Response.StatusCode = StatusCodes.Status404NotFound;
        return;
    }
    await context.Response.WriteAsJsonAsync(band);
});

The simplicity comes with a cost: it’s all very manual. I even have to convert the ID to an integer myself (not a big deal, admittedly).

How does a POST request work? I can check to see if the request is asking for JSON. With no framework or filters, my error checking is setting a status code and returning early. (I can abstract this out, obviously. It took awhile to get used to not having a framework to lean on.)

endpoints.MapPost("/bands", async context =>
{
    var repository = context.RequestServices.GetService<SampleContext>();

    if (!context.Request.HasJsonContentType())
    {
        context.Response.StatusCode = StatusCodes.Status415UnsupportedMediaType;
        return;
    }

    var band = await context.Request.ReadFromJsonAsync<Band>();
    await repository.SaveChangesAsync();
    await context.Response.WriteAsJsonAsync(band);
});

In the doc, Microsoft will be the first to tell you it’s for the simplest scenarios. It’ll be interesting to see what improvements come: will mimicking DI become easier? I hope so.

🤯 Kubernetes is deprecating Docker … what?

I know this is a .NET development newsletter, but these days you probably need at least a passing knowledge of containerization. To that end: this week, you may have heard something along the lines of “Kubernetes is deprecating Docker.” It sounds concerning, but Kubernetes says you probably shouldn’t worry and Docker is saying the same.

Still, it’s true: Kubernetes is deprecating Docker as a container runtime after v1.20—currently planned for late 2021.

From a high level, I think Google’s Kelsey Hightower summed it up best:

Think of it like this – Docker refactored its code base, broke up the monolith, and created a new service, containerd, which both Kubernetes and Docker now use for running containers.

Docker isn’t a magical “make me a container” button—it’s an entire tech stack. Inside of that is a container runtime, containerd. It contains a lot of bells and whistles for us when doing development work, but k8s doesn’t need it because it isn’t a person. (If it were, I’d like to have a chat.)

For k8s to get through this abstraction layer, it needs to use the Dockershim tool to get to containerd—yet another maintenance headache. Kubelets are removing Dockershims at the end of 2021, which removes Docker support. When this change comes, you just need to change your container runtime from Docker to another supported runtime.

Because this addresses a different environment than most folks use with Docker, it shouldn’t matter—the install you’re using in dev is typically different than the runtime in your k8s cluster. This change would largely impact k8s administrators and not developers.

Hopefully this clears up some potential confusion. We don’t talk about Docker and Kubernetes often, but this was too important not to discuss. (I could hardly contain myself.)

🌎 Last week in the .NET world

🔥 The Top 3

📢 Announcements

📅 Community and events

😎 ASP.NET Core / Blazor

🚀 .NET 5

⛅ The cloud

📔 Languages

🔧 Tools

📱 Xamarin

👍 Design, architecture and best practices

🎤 Podcasts

🎥 Videos

.NET Stacks