# Minimal API > **Note**: Requires .NET 6+ ```cs var builder = WebApplication.CreateBuilder(args); builder.Services.AddSingleton(); builder.Services.AddScoped(); builder.Services.AddTransient(); var app = builder.Build(); // [...] app.Run(); //or app.RunAsync(); ``` ## Swagger ```cs builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); // [...] app.UseSwagger(); app.UseSwaggerUI(); // add returned content metadata to Swagger app.MapGet("/route", Handler).Produces(statusCode); // add request body contents metadata to Swagger app.MapPost("/route", Handler).Accepts(contentType); ``` ## MVC ```cs builder.Services.AddControllersWithViews(); //or builder.Services.AddControllers(); // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/Home/Error"); // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.UseAuthorization(); app.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); ``` ## Routing, Handlers & Results To define routes and handlers using Minimal APIs, use the `Map(Get|Post|Put|Delete)` methods. ```cs // the dependencies are passed as parameters in the handler delegate app.MapGet("/route/{id}", (IService service, int id) => { return entity is not null ? Results.Ok(entity) : Results.NotFound(); }); // pass delegate to use default values app.MapGet("/search/{id}", Search); IResult Search(int id, int? page = 1, int? pageSize = 10) { /* ... */ } ``` ## Context With Minimal APIs it's possible to access the contextual information by passing one of the following types as a parameter to your handler delegate: - `HttpContext` - `HttpRequest` - `HttpResponse` - `ClaimsPrincipal` - `CancellationToken` (RequestAborted) ```cs app.MapGet("/hello", (ClaimsPrincipal user) => { return "Hello " + user.FindFirstValue("sub"); }); ``` ## Validation Using [Minimal Validation](https://github.com/DamianEdwards/MinimalValidation) by Damian Edwards. Alternatively it's possible to use [Fluent Validation](https://fluentvalidation.net/). ```cs app.MapPost("/widgets", (Widget widget) => { var isValid = MinimalValidation.TryValidate(widget, out var errors); if(isValid) { return Results.Created($"/widgets/{widget.Name}", widget); } return Results.BadRequest(errors); }); class Widget { [Required, MinLength(3)] public string? Name { get; set; } public override string? ToString() => Name; } ``` ## JSON Serialization ```cs // Microsoft.AspNetCore.Http.Json.JsonOptions builder.Services.Configure(opt => { opt.SerializerOptions.PropertyNamingPolicy = new SnakeCaseNamingPolicy(); }); ``` ## Authorization ```cs builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(); builder.Services.AddAuthorization(); // or builder.Services.AddAuthorization(options => { // for all endpoints options.FallbackPolicy = new AuthorizationPolicyBuilder() .AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme) .RequireAuthenticatedUser(); }) // [...] app.UseAuthentication(); app.UseAuthorization(); // must come before routes // [...] app.MapGet("/alcohol", () => Results.Ok()).RequireAuthorization(""); // on specific endpoints app.MapGet("/free-for-all", () => Results.Ok()).AllowAnonymous(); ``` ## Output Caching ```cs builder.Services.AddOutputCaching(); // no special options builder.Services.AddOutputCaching(options => { options => options.AddBasePolicy(x => x.NoCache()) // no cache policy Func predicate = /* discriminate requests */ options.AddBasePolicy(x => x.With(predicate).CachePolicy()); options.AddBasePolicy("", x => x.CachePolicy()); // named policy }); // [...] app.UseOutputCaching(); // following middlewares can use output cache // [...] app.MapGet("/", RouteHandler).CacheOutput(); // cache forever app.MapGet("/", RouteHandler).CacheOutput().Expire(timespan); app.MapGet("/", RouteHandler).CacheOutput(x => x.CachePolicy()); app.MapGet("/", RouteHandler).CacheOutput(""); app.MapGet("/", RouteHandler).CacheOutput(x => x.VaryByHeader(/* headers list */)); app.MapGet("/", RouteHandler).CacheOutput(x => x.VaryByQuery(/* query key */)); app.MapGet("/", RouteHandler).CacheOutput(x => x.VaryByValue()); app.MapGet("/", [OutputCache(/* options */)]RouteHandler); ``` ### Cache Eviction ```cs app.MapGet("/", RouteHandler).CacheOutput(x => x.Tag("")); // tag cache portion app.MapGet("/", (IOutputCacheStore cache, CancellationToken token) => { await cache.EvictByTag("", token); // invalidate a portion of the cache }); ``` ### Custom Cache Policy ```cs app.MapGet("/", RouteHandler).CacheOutput(x => x.AddCachePolicy()); ``` ```cs class CustomCachePolicy : IOutputCachePolicy { public ValueTask CacheRequestAsync(OutputCacheContext context, CancellationToken cancellationToken) { } public ValueTask ServeFromCacheAsync(OutputCacheContext context, CancellationToken cancellationToken) { } public ValueTask ServeResponseAsync(OutputCacheContext context, CancellationToken cancellationToken) { } } ```