aspnetcore/fundamentals/minimal-apis.md
:::moniker range=">= aspnetcore-10.0"
This document:
The Minimal APIs consist of:
The following table lists some of the middleware frequently used with Minimal APIs.
The following sections cover request handling: routing, parameter binding, and responses.
A configured WebApplication supports Map{Verb} and xref:Microsoft.AspNetCore.Builder.EndpointRouteBuilderExtensions.MapMethods%2A where {Verb} is a camel-cased HTTP method like Get, Post, Put, or Delete:
The xref:System.Delegate arguments passed to these methods are called "route handlers".
[!INCLUDE route handling]
Enabling validation allows the ASP.NET Core runtime to perform validations defined on the:
Validations are defined using attributes in the DataAnnotations namespace.
When a parameter to a Minimal API endpoint is a class or record type, validation attributes are automatically applied. For example:
public record Product(
[Required] string Name,
[Range(1, 1000)] int Quantity);
Developers customize the behavior of the validation system by:
[Validation] attribute implementations.IValidatableObject interface for complex validation logic.If validation fails, the runtime returns a 400 - Bad Request response with details of the validation errors.
Enable the built-in validation support for Minimal APIs by calling the AddValidation extension method to register the required services in the service container for your application:
builder.Services.AddValidation();
The implementation automatically discovers types that are defined in Minimal API handlers or as base types of types defined in Minimal API handlers. An endpoint filter performs validation on these types and is added for each endpoint.
Validation can be disabled for specific endpoints by using the DisableValidation extension method, as in the following example:
app.MapPost("/products",
([EvenNumber(ErrorMessage = "Product ID must be even")] int productId, [Required] string name)
=> TypedResults.Ok(productId))
.DisableValidation();
Customize error responses from Minimal API validation logic with an xref:Microsoft.AspNetCore.Http.IProblemDetailsService implementation. Register this service in your application's service collection to enable more consistent and user-specific error responses. Support for Minimal API validation was introduced in ASP.NET Core in .NET 10.
To implement custom validation error responses:
For more information on customizing validation error responses with IProblemDetailsService, see xref:fundamentals/minimal-apis/responses#customize-validation-error-responses-using-iproblemdetailsservice.
Route handlers support the following types of return values:
IResult based - This includes Task<IResult> and ValueTask<IResult>string - This includes Task<string> and ValueTask<string>T (Any other type) - This includes Task<T> and ValueTask<T>| Return value | Behavior | Content-Type |
|---|---|---|
IResult | The framework calls IResult.ExecuteAsync | Decided by the IResult implementation |
string | The framework writes the string directly to the response | text/plain |
T (Any other type) | The framework JSON-serializes the response | application/json |
For a more in-depth guide to route handler return values see xref:fundamentals/minimal-apis/responses
app.MapGet("/hello", () => "Hello World");
app.MapGet("/hello", () => new { Message = "Hello World" });
The following code returns a xref:Microsoft.AspNetCore.Http.TypedResults:
app.MapGet("/hello", () => TypedResults.Ok(new Message() { Text = "Hello World!" }));
Returning TypedResults is preferred to returning xref:Microsoft.AspNetCore.Http.Results. For more information, see TypedResults vs Results.
app.MapGet("/hello", () => Results.Ok(new { Message = "Hello World" }));
The following example uses the built-in result types to customize the response:
app.MapGet("/hello", () => Results.Json(new { Message = "Hello World" }));
app.MapGet("/405", () => Results.StatusCode(405));
app.MapGet("/text", () => Results.Text("This is some text"));
<a name="stream7"></a>
var proxyClient = new HttpClient();
app.MapGet("/pokemon", async () =>
{
var stream = await proxyClient.GetStreamAsync("http://contoso/pokedex.json");
// Proxy the response as JSON
return Results.Stream(stream, "application/json");
});
See xref:fundamentals/minimal-apis/responses#stream7 for more examples.
app.MapGet("/old-path", () => Results.Redirect("/new-path"));
app.MapGet("/download", () => Results.File("myfile.text"));
<a name="binr7"></a>
[!INCLUDE results-helpers]
Use the HttpResponse object to modify response headers:
app.MapGet("/", (HttpContext context) => {
// Set a custom header
context.Response.Headers["X-Custom-Header"] = "CustomValue";
// Set a known header
context.Response.Headers.CacheControl = $"public,max-age=3600";
return "Hello World";
});
Applications can control responses by implementing a custom xref:Microsoft.AspNetCore.Http.IResult type. The following code is an example of an HTML result type:
We recommend adding an extension method to xref:Microsoft.AspNetCore.Http.IResultExtensions?displayProperty=fullName to make these custom results more discoverable.
The xref:Microsoft.AspNetCore.Http.IResult interface can represent values returned from Minimal APIs that don't utilize the implicit support for JSON serializing the returned object to the HTTP response. The static Results class is used to create varying IResult objects that represent different types of responses. For example, setting the response status code or redirecting to another URL.
The types implementing IResult are public, allowing for type assertions when testing. For example:
You can look at the return types of the corresponding methods on the static TypedResults class to find the correct public IResult type to cast to.
See xref:fundamentals/minimal-apis/responses for more examples.
For more information, see xref:fundamentals/minimal-apis/min-api-filters.
Routes can be protected using authorization policies. These can be declared via the [Authorize] attribute or by using the xref:Microsoft.AspNetCore.Builder.AuthorizationEndpointConventionBuilderExtensions.RequireAuthorization%2A method:
The preceding code can be written with xref:Microsoft.AspNetCore.Builder.AuthorizationEndpointConventionBuilderExtensions.RequireAuthorization%2A:
The following sample uses policy-based authorization:
The [AllowAnonymous]
allows unauthenticated users to access endpoints:
Routes can be CORS enabled using CORS policies. CORS can be declared via the [EnableCors] attribute or by using the
xref:Microsoft.AspNetCore.Builder.CorsEndpointConventionBuilderExtensions.RequireCors%2A method. The following samples enable CORS:
For more information, see xref:security/cors
xref:Microsoft.Extensions.DependencyInjection.ServiceProviderOptions.ValidateScopes and xref:Microsoft.Extensions.DependencyInjection.ServiceProviderOptions.ValidateOnBuild are enabled by default in the Development environment but disabled in other environments.
When ValidateOnBuild is true, the DI container validates the service configuration at build time. If the service configuration is invalid, the build fails at app startup, rather than at runtime when the service is requested.
When ValidateScopes is true, the DI container validates that a scoped service isn't resolved from the root scope. Resolving a scoped service from the root scope can result in a memory leak because the service is retained in memory longer than the scope of the request.
ValidateScopes and ValidateOnBuild are false by default in non-Development modes for performance reasons.
The following code shows ValidateScopes is enabled by default in development mode but disabled in release mode:
:::code language="csharp" source="~/../AspNetCore.Docs.Samples/fundamentals/minimal-apis/samples/ValidateOnBuildWeb/Program.cs" id="snippet_1" highlight="3,16-25":::
The following code shows ValidateOnBuild is enabled by default in development mode but disabled in release mode:
:::code language="csharp" source="~/../AspNetCore.Docs.Samples/fundamentals/minimal-apis/samples/ValidateOnBuildWeb/Program.cs" id="snippet_vob" highlight="10":::
The following code disables ValidateScopes and ValidateOnBuild in Development:
:::code language="csharp" source="~/../AspNetCore.Docs.Samples/fundamentals/minimal-apis/samples/ValidateOnBuildWeb/Program.cs" id="snippet_2":::
:::moniker-end