mirror of https://github.com/abpframework/abp.git
committed by
GitHub
1 changed files with 156 additions and 0 deletions
@ -0,0 +1,156 @@ |
|||
# New Minimal APIs features in ASP.NET Core 8.0 |
|||
|
|||
In this article, we will see the new features of Minimal APIs in ASP.NET Core 8.0. |
|||
|
|||
## Binding to forms |
|||
|
|||
We can bind to forms using the [FromForm] attribute. Let's see an example: |
|||
|
|||
```csharp |
|||
app.MapPost("/books", async ([FromForm] string name, |
|||
[FromForm] BookType bookType, IFormFile? cover, BookDb db) => |
|||
{ |
|||
var book = new Book |
|||
{ |
|||
Name = name, |
|||
BookType = bookType |
|||
}; |
|||
|
|||
if (cover is not null) |
|||
{ |
|||
var coverName = Path.GetRandomFileName(); |
|||
|
|||
using var stream = File.Create(Path.Combine("wwwroot", coverName)); |
|||
await cover.CopyToAsync(stream); |
|||
book.Cover = coverName; |
|||
} |
|||
|
|||
db.Books.Add(book); |
|||
await db.SaveChangesAsync(); |
|||
|
|||
return Results.Ok(); |
|||
}); |
|||
``` |
|||
|
|||
Another way is using the [AsParameters] attribute, the following code binds from form values to properties of the `NewBookRequest` record struct: |
|||
|
|||
```csharp |
|||
public record NewBookRequest([FromForm] string Name, [FromForm] BookType BookType, IFormFile? Cover); |
|||
|
|||
app.MapPost("/books", async ([AsParameters] NewBookRequest request, BookDb db) => |
|||
{ |
|||
var book = new Book |
|||
{ |
|||
Name = request.Name, |
|||
BookType = request.BookType |
|||
}; |
|||
|
|||
if (request.Cover is not null) |
|||
{ |
|||
var coverName = Path.GetRandomFileName(); |
|||
|
|||
using var stream = File.Create(Path.Combine("wwwroot", coverName)); |
|||
await request.Cover.CopyToAsync(stream); |
|||
book.Cover = coverName; |
|||
} |
|||
|
|||
db.Books.Add(book); |
|||
await db.SaveChangesAsync(); |
|||
|
|||
return Results.Ok(); |
|||
}); |
|||
``` |
|||
|
|||
## Antiforgery |
|||
|
|||
ASP.NET Core 8.0 adds support for antiforgery tokens. We can call the `AddAntiforgery` method to register the antiforgery services and `WebApplicationBuilder` will automatically add the antiforgery middleware to the pipeline: |
|||
|
|||
```csharp |
|||
var builder = WebApplication.CreateBuilder(); |
|||
|
|||
builder.Services.AddAntiforgery(); |
|||
|
|||
var app = builder.Build(); |
|||
|
|||
// Implicitly added by WebApplicationBuilder if AddAntiforgery is called. |
|||
// app.UseAntiforgery(); |
|||
|
|||
app.MapGet("/", () => "Hello World!"); |
|||
|
|||
app.Run(); |
|||
``` |
|||
|
|||
Example of using antiforgery tokens: |
|||
|
|||
```csharp |
|||
|
|||
// Use the antiforgery service to generate tokens. |
|||
app.MapGet("/", (HttpContext context, IAntiforgery antiforgery) => |
|||
{ |
|||
var token = antiforgery.GetAndStoreTokens(context); |
|||
return Results.Content(...., "text/html"); |
|||
}); |
|||
|
|||
// It will automatically validate the token. |
|||
app.MapPost("/todo", ([FromForm] Todo todo) => Results.Ok(todo)); |
|||
|
|||
// Disable antiforgery validation for this endpoint. |
|||
app.MapPost("/todo2", ([FromForm] Todo todo) => Results.Ok(todo)) |
|||
.DisableAntiforgery(); |
|||
``` |
|||
|
|||
|
|||
## Native AOT |
|||
|
|||
ASP.NET Core 8.0 adds support for Native AOT. |
|||
|
|||
You can add `PublishAot` to the project file to enable Native AOT: |
|||
|
|||
```xml |
|||
<PropertyGroup> |
|||
<PublishAot>true</PublishAot> |
|||
</PropertyGroup> |
|||
``` |
|||
|
|||
### Web API (native AOT) template |
|||
|
|||
You can use the `dotnet new webapiaot` command to create a new Minimal APIs project with Native AOT enabled. |
|||
|
|||
```diff |
|||
+using System.Text.Json.Serialization; |
|||
|
|||
-var builder = WebApplication.CreateBuilder(); |
|||
+var builder = WebApplication.CreateSlimBuilder(args); |
|||
|
|||
+builder.Services.ConfigureHttpJsonOptions(options => |
|||
+{ |
|||
+ options.SerializerOptions.TypeInfoResolverChain.Insert(0, AppJsonSerializerContext.Default); |
|||
+}); |
|||
|
|||
var app = builder.Build(); |
|||
|
|||
var sampleTodos = TodoGenerator.GenerateTodos().ToArray(); |
|||
|
|||
var todosApi = app.MapGroup("/todos"); |
|||
todosApi.MapGet("/", () => sampleTodos); |
|||
todosApi.MapGet("/{id}", (int id) => |
|||
sampleTodos.FirstOrDefault(a => a.Id == id) is { } todo |
|||
? Results.Ok(todo) |
|||
: Results.NotFound()); |
|||
|
|||
app.Run(); |
|||
|
|||
+[JsonSerializable(typeof(Todo[]))] |
|||
+internal partial class AppJsonSerializerContext : JsonSerializerContext |
|||
+{ |
|||
+ |
|||
+} |
|||
``` |
|||
|
|||
* Reflection isn't supported in native AOT, you must use the `JsonSerializable` attribute to specify the types that you want to serialize/deserialize. |
|||
|
|||
## References |
|||
|
|||
* https://learn.microsoft.com/en-us/aspnet/core/release-notes/aspnetcore-8.0?view=aspnetcore-8.0#minimal-apis |
|||
* https://learn.microsoft.com/en-us/aspnet/core/fundamentals/minimal-apis/parameter-binding?view=aspnetcore-8.0#explicit-binding-from-form-values |
|||
* https://learn.microsoft.com/en-us/aspnet/core/fundamentals/native-aot?view=aspnetcore-8.0 |
|||
Loading…
Reference in new issue