Reputation: 2285
Say I want to have 2 endpoints, /a
and /b
, while also utilizing the pipeline branching for both of those endpoints, for adding custom middleware for them.
The following code does not work:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
var a = "/a";
var b = "/b";
app.Map(a, true, branch =>
{
branch.Use((context, next) =>
{
context.Response.Headers.Add("X-Test", "a");
return next(context);
});
});
app.Map(b, true, branch =>
{
branch.Use((context, next) =>
{
context.Response.Headers.Add("X-Test", "b");
return next(context);
});
});
app.MapGet(a, () => "hello from a!");
app.MapGet(b, () => "hello from b!");
app.Run();
Calling /a
fails with:
System.InvalidOperationException: The request reached the end of the pipeline without executing the endpoint: 'HTTP: GET /a'. Please register the EndpointMiddleware using 'IApplicationBuilder.UseEndpoints(...)' if using routing.
at Microsoft.AspNetCore.Builder.ApplicationBuilder.<>c.<Build>b__25_0(HttpContext context)
at Program.<>c.<<Main>$>b__0_4(HttpContext context, RequestDelegate next) in C:\Users\...\RiderProjects\MinimalApiSample\MinimalApiSample\Program.cs:line 15
at Microsoft.AspNetCore.Builder.Extensions.MapMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)
But I can't figure out, where to put UseEndpoints
and why do I need it after adding custom app.Map(...
calls? I'm also not putting UseRouting
anywhere because I tried it right before the first app.Map(...
but it didn't change the outcome and apparently it's not required in Minimal API at all.
Upvotes: 1
Views: 241
Reputation: 142008
Use UseWhen
:
Conditionally creates a branch in the request pipeline that is rejoined to the main pipeline.
app.UseWhen(context => context.Request.Path == a, ab => ab.Use((context, next) =>
{
context.Response.Headers.Add("X-Test", "a");
return next(context);
}));
//... the same for the b
app.MapGet(a, () => "hello from a!");
Map
on the other hand creates just a separate branch:
Branches the request pipeline based on matches of the given request path. If the request path starts with the given path, the branch is executed.
Also see the Branch the middleware pipeline section of the docs.
UPD
if you need the separate branch then you can just build it fully. For example for /b
:
app.Map(b, true, branch =>
{
branch.Use((context, next) =>
{
context.Response.Headers.Add("X-Test", "b");
return next(context);
});
branch.UseRouting();
branch.UseEndpoints(rb => rb.MapGet(b, () => "hello from b!"));
});
Upvotes: 0
Reputation: 37367
You can use MapWhen
. Below is your example with applied corrections:
app.MapWhen(context => context.Request.Path == a, branch =>
{
branch.Run(context =>
{
context.Response.Headers.Add("X-Test", "a");
return Task.CompletedTask;
});
});
app.MapWhen(context => context.Request.Path == b, branch =>
{
branch.Run(context =>
{
context.Response.Headers.Add("X-Test", "b");
return Task.CompletedTask;
});
});
Upvotes: 0