Asp.net core Net核心-从中间件获取routetemplate值
我有一个中间件,它为我的API的每个请求调用。我想记录路由模板以及来自该中间件的请求的持续时间。如何在我的中间件代码中获取路由模板?路由模板类似于“/products/{productId}”。从自定义中间件获取路由数据并不容易,因为它是由MVC中间件创建的,MVC中间件通常是ASP.NET核心管道中执行的最后一个中间件 如果您希望在中间件中记录请求和响应,如下所示Asp.net core Net核心-从中间件获取routetemplate值,asp.net-core,Asp.net Core,我有一个中间件,它为我的API的每个请求调用。我想记录路由模板以及来自该中间件的请求的持续时间。如何在我的中间件代码中获取路由模板?路由模板类似于“/products/{productId}”。从自定义中间件获取路由数据并不容易,因为它是由MVC中间件创建的,MVC中间件通常是ASP.NET核心管道中执行的最后一个中间件 如果您希望在中间件中记录请求和响应,如下所示 public async Task Invoke(HttpContext context) { var r
public async Task Invoke(HttpContext context)
{
var requestBodyStream = new MemoryStream();
var originalRequestBody = context.Request.Body;
await context.Request.Body.CopyToAsync(requestBodyStream);
requestBodyStream.Seek(0, SeekOrigin.Begin);
var url = UriHelper.GetDisplayUrl(context.Request);
var requestBodyText = new StreamReader(requestBodyStream).ReadToEnd();
_logger.Log(LogLevel.Information, 1, $"REQUEST METHOD: {context.Request.Method}, REQUEST BODY: {requestBodyText}, REQUEST URL: {url}", null, _defaultFormatter);
requestBodyStream.Seek(0, SeekOrigin.Begin);
context.Request.Body = requestBodyStream;
await next(context);
var bodyStream = context.Response.Body;
var responseBodyStream = new MemoryStream();
context.Response.Body = responseBodyStream;
await _next(context);
responseBodyStream.Seek(0, SeekOrigin.Begin);
var responseBody = new StreamReader(responseBodyStream).ReadToEnd();
_logger.Log(LogLevel.Information, 1, $"RESPONSE LOG: {responseBody}", null, _defaultFormatter);
responseBodyStream.Seek(0, SeekOrigin.Begin);
await responseBodyStream.CopyToAsync(bodyStream);
}
然而,如果您真的对路由数据感兴趣,那么有一个非常好的答案来实现GetRoutes Miidware
另一种替代方法是用于请求/响应日志记录。以下是我如何让它工作的。我在FilterOnActionExecuting方法中获取路由模板,并将其添加到HttpContext。稍后,我从中间件中的HttpContext访问它,因为我可以访问中间件中的HttpContext
public class LogActionFilter : IActionFilter
{
public LogActionFilter()
{
}
public void OnActionExecuted(ActionExecutedContext context)
{
}
public void OnActionExecuting(ActionExecutingContext context)
{
context.HttpContext.Items.Add("RouteTemplate", context.ActionDescriptor.AttributeRouteInfo.Template);
}
}
实际上,使用ASP.NET Core 3.0+可以非常轻松地实现这一点,方法是从中间件中的
上下文中获取ControllerActionDescriptor
:
public异步任务InvokeAsync(HttpContext上下文,RequestDelegate-next)
{
Endpoint endpointBeingHit=context.Features.Get()?.Endpoint;
ControllerActionDescriptor actionDescriptor=endpointBeingHit?.Metadata?.GetMetadata();
此为.logger.LogInformation(
“匹配的路由模板{template}'”,
actionDescriptor?.AttributeRouteInfo.Template);
等待下一个();
}
您的代码示例记录实际的请求url。我想记录路由模板。这不是我想要记录的/products/product123,而是/products/{productId}。然而,我可以使用动作过滤器来获得这个。谢谢你的信息。