Scott Hanselman

Minimal APIs at a glance in .NET 6

September 07, 2021 Comment on this post [14] Posted in DotNetCore | Open Source | Web Services
Sponsored By

imageDavid Fowler doesn't have a blog. I think the psychic weight of having a blog would stress him out. Fortunately, David's 'blog' is actually hidden in his prolific GitHub commits and GitHub Gists.

David has been quietly creating  an amazing piece of documentation for Minimal APIs in .NET 6. At some point when it's released we'll work with David to get everything promoted to formal documentation, but as far as I'm concerned if he is slapping the keyboard anywhere and it shows up anywhere with a URL then I'm happy with the result!

Let's explore a bit here and I encourage you to head over to the main Gist here.

To start, we see how easy it is to make a .NET 6 (minimal) app to say Hello World over HTTP on localhost:5000/5001

var app = WebApplication.Create(args);

app.MapGet("/", () => "Hello World");

app.Run();

Lovely. It's basically nothing. Can I do more HTTP Verbs? Yes.

app.MapGet("/", () => "This is a GET");
app.MapPost("/", () => "This is a POST");
app.MapPut("/", () => "This is a PUT");
app.MapDelete("/", () => "This is a DELETE");

What about other verbs? More than one?

app.MapMethods("/options-or-head", new [] { "OPTIONS", "HEAD" }, () => "This is an options or head request ");

Lambda expressions, not objects, are our "atoms" that we build molecules with in this world. They are the building blocks.

app.MapGet("/", () => "This is an inline lambda");

var handler = () => "This is a lambda variable";

app.MapGet("/", handler)

But it's just a function, so you can organize things however you want!

var handler = new HelloHandler();

app.MapGet("/", handler.Hello);

class HelloHandler
{
public string Hello()
{
return "Hello World";
}
}

You can capture route parameters as part of the route pattern definition.

app.MapGet("/users/{userId}/books/{bookId}", (int userId, int bookId) => $"The user id is {userId} and book id is {bookId}");

Route constraints are influence the matching behavior of a route. See how this is in order of specificity:

app.MapGet("/todos/{id:int}", (int id) => db.Todos.Find(id));
app.MapGet("/todos/{text}", (string text) => db.Todos.Where(t => t.Text.Contains(text));
app.MapGet("/posts/{slug:regex(^[a-z0-9_-]+$)}", (string slug) => $"Post {slug}");

Attributes can be used to explicitly declare where parameters should be bound from! So you can pick and choose from all over!

using Microsoft.AspNetCore.Mvc;

app.MapGet("/{id}", ([FromRoute]int id,
[FromQuery(Name = "p")]int page,
[FromServices]Service service,
[FromHeader(Name = "Content-Type")]string contentType) => { });

I can customize the response:

app.MapGet("/todos/{id}", (int id, TodoDb db) => 
db.Todos.Find(id) is Todo todo
? Results.Ok(todo)
: Results.NotFound()
);

Here's a cool example of taking a file upload and writing it to a local file. Nice and clean.

app.MapGet("/upload", async (HttpRequest req) =>
{
if (!req.HasFormContentType)
{
return Results.BadRequest();
}

var form = await req.ReadFormAsync();
var file = form.Files["file"];

if (file is null)
{
return Results.BadRequest();
}

var uploads = Path.Combine(uploadsPath, file.FileName);
await using var fileStream = File.OpenWrite(uploads);
await using var uploadStream = file.OpenReadStream();
await uploadStream.CopyToAsync(fileStream);

return Results.NoContent();
})
.Accepts<IFormFile>("multipart/form-data");

Go check out this great (and growing) online resource to learn about .NET 6 minimal APIs.


Sponsor: YugabyteDB is a distributed SQL database designed for resilience and scale. It is 100% open source, PostgreSQL-compatible, enterprise-grade, and runs across all clouds. Sign up and get a free t-shirt.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Hosting By
Hosted in an Azure App Service
September 13, 2021 5:49
On the other end, would love to see more “it’s a big app” ideas that are enabled by the breakdown of the startup class. Something akin to the CarterCommunity & apb.io modules where you add routes and services in feature related slices. Almost certain to come after the pendulum reaches the “minimal” max.
September 14, 2021 4:55
Since when is this:

var handler = () => "This is a lambda variable";


valid C# syntax? Doesn't handler have to be explicitly typed as Action, Func<string>, or other compatible delegate type?
September 14, 2021 6:12
> valid C# syntax? Doesn't handler have to be explicitly typed as Action, Func<string>, or other compatible delegate type?

Since C# 10. See https://github.com/dotnet/csharplang/blob/main/proposals/csharp-10.0/lambda-improvements.md for more information.
September 14, 2021 7:26
Does anyone know what the motivation is for adding this new syntax? At least to me, I doubt that the bit of additional boiler plate code required to set up something similar in asp.net core 5 was a big problem for people building real applications?
I can see that it can make some code samples on stackoverflow more concise, but I don't really see how this is a serious productivity improvement in the real world (and I would assume Microsoft view this as a significant improvement, since it is getting much publicity)?
Thanks :)
September 14, 2021 8:53
C# looks a little more like javascript or typescript with each release. minimal API is express.js. OOP is ignored, c# is now like a functional programming language. Are you sure it's better this way?
September 14, 2021 8:58
It is absolutely beautiful and I dont get all the hate. I use .net since v1.0 and Java/.net enterprisy boilerplate was always friction for me. I wrote zillions of helpers that made it hide away just to get simple things done in conscise way.
September 14, 2021 15:35
Just being curious. Can minimal api structure be used to setup a SignalR Hub StreamAsync() and MassagePack() for C#.
September 15, 2021 14:23
@WayneO
Can minimal api structure be used to setup a SignalR Hub StreamAsync() and MassagePack() for C#.


I've not tried it myself, but I spotted an example on David Fowler's twitter stream just this morning.

(I dream of being that prolific....)
September 15, 2021 15:39
This is all BS, distractions!
// Catching exceptions is for communists ?
Owl
September 16, 2021 10:51

@Anders Olesen
Does anyone know what the motivation is for adding this new syntax? At least to me, I doubt that the bit of additional boiler plate code required to set up something similar in asp.net core 5 was a big problem for people building real applications?


My opinion is this, things change for the sake of change. A lot of tools have gotten better so there isn't a lot of efficiency lost in the current syntax. We might as well learn F# since that's where C# seems to be heading.
September 16, 2021 14:31
Just want to say your article is as astonishing. The clarity in your post is simply excellent and I could assume you’re an expert on this subject.

Fine with your permission allow me to grab your feed to keep up to date with forthcoming post. Thanks a million and please keep up the enjoyable work.
September 16, 2021 16:25
There are few useful updates in the .NET 6 new version! Being a developer, I have learned a lot of things from this post regarding what features available in the current version. Thanks for letting us know about these changes,
September 16, 2021 16:31
Thanks for letting us know about this changes in the new .NET 6 version! Honestly, speaking I was familiar with the previous version and all the features available in the latest version. By profession, I am digital marketing expert at this downblouse platform and help people with connecting with wonderful girls around the cities.
September 16, 2021 16:33
Thanks for letting us know about this changes in the new .NET 6 version! Honestly, speaking I was familiar with the previous version and all the features available in the latest version. By profession, I am digital marketing expert at this platform and help people with connecting with wonderful girls around the cities.

Comments are closed.

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.