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.
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
- Niels Swimberghe makes phone calls from Blazor WebAssembly with Twilio Voice. (And while you’re there, hover over the burger. You’re welcome.)
- Steve Smith warns against wrapping DbContext in using, and other gotchas.
- Khalid Abuhakmeh writes about understanding the .NET 5 runtime environment.
📢 Announcements
- Claire Novotny shines a light on debug-time productivity with Source Link.
- .NET Core 2.1, 3.1, and 5.0 updates are coming to Microsoft Update.
- Uno Platform 3.1 is released.
- Scott Addie recaps what’s new in the ASP.NET Core docs for November 2020.
- Bri Achtman writes about ML.NET Model Builder November updates.
- Tara Overfield releases the November 2020 cumulative update preview for .NET Framework.
📅 Community and events
- Just one community standup this week: Xamarin talks about .NET MAUI.
- The .NET Docs Show talks to Dave Brock (yes, that one) about C# 9.
😎 ASP.NET Core / Blazor
- Dave Brock writes about simple JSON APIs with ASP.NET Core route-to-code.
- David Ramel writes about reported performance degradation when moving from WinForms to Blazor.
- Ricardo Peres writes about the pitfalls when working with async file uploads in ASP.NET Core.
- Jon Hilton passes arguments to onclick functions in Blazor.
- Marinko Spasojevic writes about complex model validation in Blazor apps.
- Damien Bowden secures an ASP.NET Core API that uses multiple access tokens.
- Michael Shpilt writes about some must-know packages for ASP.NET Core.
🚀 .NET 5
- Jonathan Allen writes more about .NET 5 breaking changes.
- Eran Stiller writes about .NET 5 runtime improvements.
- Jonathan Allen writes about .NET 5 breaking changes to the BCL.
- Antonio Laccardi writes about ASP.NET Core improvements in .NET 5.
- Norm Johnson writes about .NET 5 AWS Lambda support with container images.
⛅ The cloud
- Frank Boucher configures a secured custom domain on an Azure Function or website.
- Paul Michaels handles events inside an Azure Function.
- David Ramel writes how Google Cloud Functions supports .NET Core 3.1 but not .NET 5.
- Abel Wang and Isaac Levin write about dev productivity with GitHub, VS Code, and Azure.
📔 Languages
- Claudio Bernasconi writes about top-level statements in C# 9, and also works through switch expressions in C# 8.
- Munib Butt uses the proxy pattern in C#.
- Ian Russell introduces partial function application in F#.
- Ian Griffiths shows the pitfalls of mechanism over intent with C# 9 patterns.
- Matthew Crews writes about object expressions in F#.
🔧 Tools
- Sean Killeen gets started with PowerShell Core in Windows Terminal, and also writes about things he’s learned about NUnit.
- Andrew Lock uses Quartz.NET with ASP.NET Core and worker services.
📱 Xamarin
- James Montemagno warns against using Android in your namespaces, and also gets you writing your first app for iOS and Android with Xamarin and Visual Studio.
- Yogeshwaran Mohan creates a marquee control.
- Nick Randolph explains the correlation between .NET 5, WinUI, and MAUI (Xamarin.Forms).
- Matheus Castello writes about Linux + .NET 5 + VS Code XAML Preview + Hot Reload running on embedded Linux.
👍 Design, architecture and best practices
- Kamil Grzybek continues his series on modular monoliths.
- Scott Brady reminds us: OAuth is not user authorization.
- Peter Vogel shows the advantages of end-to-end testing.
- Nathan Bennett compares GraphQL to REST.
- Derek Comartin talks about handling duplicate messages.
🎤 Podcasts
- The Changelog talks about growing as a software engineer.
- The Stack Overflow podcast explains why devs are increasing demanding ethics in tech.
- The 6 Figure Developer talks to Rob Richardson about .NET 5, pipelines, and testing.
🎥 Videos
- Jeff Fritz works with Entity Framework Core.
- The ON.NET Show customizes the Graph SDKs and discusses microcontrollers with the Meadow IoT platform.
- Data Exposed gets started with DevOps for Azure SQL.
- The Loosely Coupled Show talks about the difficulties of caching.