读取中间件.Net Core中的Controller和Action名称

问题描述 投票:0回答:6

我正在我的项目中编写一个中间件类,以便将请求数据记录到我们的数据库中。

我没有看到任何简单的方法来获取控制器名称和操作? 有机会在核心中轻松做到这一点吗?

我有这样的东西:

public class RequestResponseLoggingMiddleware
{
    private readonly RequestDelegate _next;

    public RequestResponseLoggingMiddleware(RequestDelegate next)
    {
        _next = next;            
    }

    public async Task Invoke(HttpContext context)
    {        
        //handle the request
        //something like: context.GetRouteData();

        await _next(context);                 

        //handle the response
    }       
}
c# asp.net-core middleware
6个回答
60
投票

我遇到了同样的问题,这在 .NetCore 3.1 中对我有用:

public async Task InvokeAsync(HttpContext httpContext)
{
    var controllerActionDescriptor = httpContext
        .GetEndpoint()
        .Metadata
        .GetMetadata<ControllerActionDescriptor>();

    var controllerName = controllerActionDescriptor.ControllerName;
    var actionName = controllerActionDescriptor.ActionName;
            
    await _next(httpContext);
}

为了让

GetEndpoint()
返回实际端点而不是 null,必须满足以下条件。

  • 启用端点路由(
    AddControllers()
    而不是
    AddMvc()
  • UseRouting()
    UseEndpoints()
    之间调用您的中间件。

8
投票

在 Ganesh 的回答中我想添加一些条件。

  • 启用端点路由(
    AddControllers()
    而不是
    AddMvc()
  • UseRouting()
    UseEndpoints()
    之间调用您的中间件。

否则

GetEndpoint()
返回 null。


6
投票

这可行,但您需要确保在查询控制器和操作名称之前调用

_next(context)

public async Task InvokeAsync(HttpContext context)
{
    await _next(context);

    var controllerName = context.GetRouteData().Values["controller"];
    var actionName = context.GetRouteData().Values["action"];
}

3
投票

在 .NET Core 2.0 中,您可以在过滤器中执行此操作:

public class AuthorizationFilter : IAsyncAuthorizationFilter
    {
        public async Task OnAuthorizationAsync(AuthorizationFilterContext context)
        {
            var controllerActionDescriptor = context.ActionDescriptor as ControllerActionDescriptor;
            string controllerName = controllerActionDescriptor?.ControllerName;
            string actionName = controllerActionDescriptor?.ActionName;
        }
    }

0
投票

控制器和操作数据可通过过滤器获得,因此我以这种方式实现。控制器和操作数据在 ActionExecutingContext 对象中可用。

public class AsyncActionFilter : IAsyncActionFilter
{
     public AsyncActionFilter(IEntityContext entityContext)
     {
         _entityContext = entityContext;
     }

     public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
     {  
          //Handle the request
          await next();
     }
}

0
投票

@Ganesh的答案很好,但对我不起作用,因为我正在使用.NET 6和OrchardCore,它使用自己的

AddMVC()
(不允许我使用
AddControllers()
UseRouting()
UseEndpoints()
)。

我的解决方案有效,因为我只需要控制器名称,并且没有使用路由参数或查询字符串,因此我可以轻松解析 API 路径:

public async Task InvokeAsync(HttpContext context, RequestDelegate next)
{
    // parse API path, assuming no route parameters, no querystring
    var requestPath = context.Request?.Path.Value ?? "";
    var controller = requestPath.Substring(requestPath.LastIndexOf('/') + 1);

    if (controller.ToLowerInvariant() == "mycontroller")
    {
        // ...
    }

    await next(context);
}
© www.soinside.com 2019 - 2024. All rights reserved.