The .NET Stacks #44: 🐦 APIs that are light as a feather
Happy Monday! Here’s what we’re talking about this week:
- One big thing: Looking at the FeatherHttp project
- The little things: Azure Static Web apps with DevOps, new OSS badges, coding tip
- Last week in the .NET world
One big thing: Looking at the FeatherHttp project
We’ve talked in the past about ASP.NET Core MVC APIs and their role in the .NET Core ecosystem. While MVC has received performance improvements and does what it sets out to do, it carries a lot of overhead and is often reminiscent of the “here you go, have it all” reputation of .NET Framework. It’s a robust solution that allows you to build complex APIs but comes with a lot of ceremony. With imperative frameworks like Go and Express, you can get started immediately and with little effort. No one has said the same about writing APIs in ASP.NET Core. It’s a bad look on the framework in general, especially when folks want to try out .NET for the first time.
Last year, Dapr pushed cross-platform samples for the major frameworks, and this tweet shows a common theme with MVC:
Can we have solutions that allow you to get started quickly and avoid this mess? What if you aren’t a fan of controllers? You could use external libraries like MediatR or API Endpoints, or a framework like Nancy—but it still feels like the native runtime deserves better. The ASP.NET Core team has thought about this for a while.
The route-to-code alternative is a great start, which I wrote about. It allows you to write simple JSON APIs, using an API endpoints model—with some helper methods that lend a hand.
Here’s a quick example:
app.UseEndpoints(endpoints =>
{
endpoints.MapGet("/hello/{name:alpha}", async context =>
{
var name = context.Request.RouteValues["name"];
await context.Response.WriteAsJsonAsync(new { message = $"Hello {name}!" });
});
});
It’s great, but Microsoft will tell you it’s only for simple APIs. Their docs clearly state: Route-to-code is designed for basic JSON APIs. It doesn’t have support for many of the advanced features provided by ASP.NET Core Web API. This begs the question: will .NET ever have a modern, lightweight API solution that has a low barrier to entry and also scales? Can I have a lightweight API that starts small and allows me to add complex features as I need them?
That is the goal of FeatherHttp, a project from ASP.NET Core architect David Fowler. Triggered by Kristian’s tweet, Fowler says the repo has three key goals: to be built on the same primitives on .NET Core, to be optimized to build HTTP APIs quickly, and having the ability to take advantage of existing .NET Core middleware and frameworks. According to a GitHub comment, the solution uses 90% of ASP.NET Core and changes the Startup pattern to be more lightweight. You can also check out a tutorial that walks you through building the backend of a React app with basic CRUD APIs and some serialization.
Here’s an example:
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
var app = WebApplication.Create(args);
app.MapGet("/", async http =>
{
await http.Response.WriteAsync("Hello World");
});
await app.RunAsync();
Is this a fun experiment (currently at version 0.1.82-alpha) or will it make its way into ASP.NET Core? I’m not a mind reader, my friends, but I do know two things: (1) David Fowler is the partner architect on ASP.NET Core, and (2) big objectives for .NET 6 are to appeal to new folks and to improve the developer inner-loop experience. I suspect we’ll be hearing a lot more about this. Stay tuned.
The little things: Azure Static Web apps with DevOps, new OSS badges, code complexity tip
Last week, Microsoft announced that Azure Static Web Apps supports deployment through Azure DevOps YAML pipelines. I wrote about it as well. It opens doors for many corporate customers who aren’t ready to move to GitHub yet—while they’ve made great strides, GitHub still has some work to do to match the robust enterprise capabilities of Azure DevOps.
I was able to move one of my projects over seamlessly. Unlike GitHub Actions, Azure DevOps handles PR triggers for you automatically, so my YAML is pretty clean:
trigger:
- main
pool:
vmImage: 'ubuntu-latest'
steps:
- task: AzureStaticWebApp@0
inputs:
app_location: "BlastOff.Client"
api_location: "BlastOff.Api"
output_location: "wwwroot"
env:
azure_static_web_apps_api_token: $(deployment_token)
While it isn’t as streamlined and elegant as the GitHub experience—you need to configure your deployment token manually, and you don’t get automatic staging environments—this should help improve adoption. If you’re wondering whether to use Azure Static Web Apps with Azure DevOps or GitHub, I’ve got you covered.
The ASP.NET Core team has introduced “good first issue” and “Help wanted” GitHub badges. If you’ve ever wanted to contribute to ASP.NET Core but didn’t know where to start, this might help.
Sometimes, it seems that processing a collection of objects is half of a developer’s job. It can often be a subject of abuse, especially when it comes to nested loops and their poor performance.
Here’s an example of me iterating through a list of Blogger
objects, checking if a Url
exists, and adding it to a list. (I’m using records and target-typed expressions for brevity.)
using System.Collections.Generic;
var result = new List<string>();
var bloggers = new List<Blogger>
{
new("Dave Brock", "https://daveabrock.com", true),
new("James Clear", "https://jamesclear.com", false)
};
foreach (var blogger in bloggers)
{
if (blogger.IsTechBlogger)
{
var url = blogger.Url;
if (url is not null)
result.Add(url);
}
}
record Blogger(string Name, string Url, bool IsTechBlogger);
Instead, try a LINQ collection pipeline:
using System.Collections.Generic;
using System.Linq;
var urlList = new List<string>();
var bloggers = new List<Blogger>
{
new("Dave Brock", "https://daveabrock.com", true),
new("James Clear", "https://jamesclear.com", false)
};
urlList = bloggers.Where(b => b.IsTechBlogger)
.Select(u => u.Url)
.Where(u => u is not null).ToList();
record Blogger(string Name, string Url, bool IsTechBlogger);
🌎 Last week in the .NET world
🔥 The Top 4
- Nish Anil writes about monitoring and observability in cloud-native ASP.NET Core apps.
- Dave Brock uses Azure Static Web Apps with Azure DevOps pipelines.
- Michael Shpilt maximizes the power of logs as applications scale.
- Vladimir Khorikov asks: are static methods evil?
📢 Announcements
- Azure Static Web Apps now supports deployment with Azure DevOps.
- GitHub Desktop now supports cherry-picking.
- Alvin Ashcraft has released his book on WinUI 3..
- Nicholas Blumhardt announces Serilog Expressions 2.0.
- PostSharp 6.9 is live with Visual Studio Tooling performance improvements.
- Andrew Clinick announces Project Reunion 0.5.
- .NET Standard 1.3 is no longer supported in AWS SDK for .NET version 3.7.
- David Guida’s OpenSleigh project has been sponsored by JetBrains.
📅 Community and events
- Matt Lacey builds a Visual Studio extension to navigate between ANY files.
- For community standups: Xamarin previews .NET 6 updates and ASP.NET talks about 12-factor apps.
- Because NuGet stores download counts in Int32, in 80 weeks the NewtonSoft.Json package will overflow it.
- Microsoft Build will occur on May 25-27.
🌎 Web development
- Matthew Jones continues writing a Tetris game in Blazor.
- Mukesh Murugan builds a chat application with Blazor, Identity, and SignalR.
- Niels Swimberghe deploys Blazor WebAssembly apps to DigitalOcean.
- Sundaram Subramanian writes about using the MudBlazor library for breadcrumbs.
- David Hayden works with ASP.NET Core user secrets and the Secret Manager tool.
- Claudio Bernasconi writes a Blazor dialog component in .NET 5, and also handles CSS in Blazor.
- Marinko Spasojevic works with Material UI in Blazor.
🥅 The .NET platform
- Khalid Abuhakmeh handles exceptions with ASP.NET Core ExceptionHandlerMiddleware .
- Matthew MacDonald writes about the future of Windows apps.
- Peter Vogel writes about Project Reunion.
⛅ The cloud
- Paul Michaels writes about auto-deleting Azure Service Bus messages when idle.
- Khalid Abuhakmeh builds mono-repos with GitHub Actions.
- Jon Gallant works with Azure REST APIs with Postman’s OAuth 2.0 Provider.
- Aaron Powell writes about simplifying auth for Azure Static Web App APIs.
📔 Languages
- Tom Deseyn writes about C# 9 top-level programs and target-typed expressions.
- Shawn Wildermuth demystifies bitwise operators in C#.
🔧 Tools
- Clyde D’Souza explores GitHub Actions fundamentals.
- Richard Reedy writes about the .NET Upgrade Assistant.
- Scott Hanselman writes about recent updates to the Windows Terminal.
- Julio Sampaio stress tests .ET apps with Apache JMeter.
- Yannick Reekmans adds the Developer PowerShell and Developer Command Prompt for Visual Studio to Windows Terminal.
- James Montemagno explores code Generation from XAML in Visual Studio.
📱 Xamarin
- Luis Matos handles global errors .
- Sam Basu provides another MAUI update.
- James Montemagno sets Up an M1 Mac for Xamarin development.
🏗 Design, testing, and best practices
- Jason Farrell addresses a misconception that serverless is good for APIs.
- James Shore writes about TDD.
- Oleksii Holubiev writes about .NET authentication.
- Genevieve Michaels writes about providing feedback to your manager without being a jerk.
- Derek Comartin discusses the pitfalls of using REST APIs for microservices.
- Patrick Smacchia writes about 8 books for .NET developers.
- Rossitza Fakalieva unit tests some C# 8 and 9 features.
- James Hickey writes about scaling your auth system.
🎤 Podcasts
- The Adventures in .NET podcast talks about application monitoring.
- The 6-Figure Developer podcast talks about reactive DDD with Vaughn Vernon.
- The .NET Core Podcast discusses C# and .NET for beginners with Vijesh Salian.
- The Complete Developer podcast talks about side hustle failures.
🎥 Videos
- Over at Ask the Expert, a discussion with Dr. Brian Kernighan, the inventor of “Hello, World.”
- The On .NET Show integrates PowerApps with .NET Web APIs, discusses the .NET Upgrade Assistant, and integrates PowerApps with .NET Web APIs.
- The ASP.NET Monsters discuss Microsoft Identity with Christos Matskas.
- The AI Show extracts information from documents with Form Recognizer.