webapi中间件没有使用终结点中间件时的注意事项
最小webapi
最小webapi默认的中间件配置是这样的
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
最小webapi没有使用app.UseRouting()
和app.UseEndpoints
。
这种情况下我们添加的所有中间件其实都是位于终结点路由中间件EndpointRoutingMiddleware
和终结点中间件EndpointMiddleware
之间的中间件。
也就是说这些中间件全都执行了之后,Action才会执行。
加入我们写了一个自定义404页面的中间件,并把它注册进去。
app.Use(async (context, next) =>
{
context.Response.StatusCode = StatusCodes.Status404NotFound;
context.Response.ContentType = "text/html;charset=utf-8";
context.Response.WriteAsync("来到了知识的荒原");
await next(context);
});
这个中间件不会以我们预料的方式运行,他会在每次请求中都被调用,而不是找不到路由时才调用。
就是因为没有注册app.UseEndpoints
的终结点中间件时,不存在终结点之后的中间件。而终结点之后的中间件才会在找不到路由,找不到终结点时被调用。
终结点中间件应该是在找到了终结点时会短路管道,找不到时调用next(context)
。
所以我们必须显式调用app.UseEndpoints
,然后再到后面再注册我们的404中间件。这才会达到我们的预期。
必须注意的的是如果app.UseEndpoints
被调用,那么app.UseRouting()
也必须被调用。
所以这种情况下正确的写法是
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.MapControllers();
app.UseEndpoints(endpoints=>{});
app.Use(async (context, next) =>
{
context.Response.StatusCode = StatusCodes.Status404NotFound;
context.Response.ContentType = "text/html;charset=utf-8";
context.Response.WriteAsync("来到了知识的荒原");
await next(context);
});
app.Run();
检验
我们可以取一下终结点信息看看是不是这样
app.Use(async (context, next) =>
{
var endpoint = context.GetEndpoint();
await next(context);
});
把这个中间件添加到app.UseRouting()
之前,app.UseRouting()
之后,再加一个到app.UseEndpoints
之后。
我们能发现只有再app.UseRouting()
和app.UseRouting()
之间的那个中间件才能取到终结点信息,其他的两个里面终结点endpoint = null
MSDN
最小webapi中的默认情况下,我们的中间件就在图中Custom middlewares
的地方。我们改了之后就能同时在Endpoint
之后加中间件了。