Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-core/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Asp.net core Net核心-从中间件获取routetemplate值_Asp.net Core - Fatal编程技术网

Asp.net core Net核心-从中间件获取routetemplate值

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

我有一个中间件,它为我的API的每个请求调用。我想记录路由模板以及来自该中间件的请求的持续时间。如何在我的中间件代码中获取路由模板?路由模板类似于“/products/{productId}”。

从自定义中间件获取路由数据并不容易,因为它是由MVC中间件创建的,MVC中间件通常是ASP.NET核心管道中执行的最后一个中间件

如果您希望在中间件中记录请求和响应,如下所示

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}。然而,我可以使用动作过滤器来获得这个。谢谢你的信息。