我正在我的项目中编写一个中间件类,以便将请求数据记录到我们的数据库中。
我没有看到任何简单的方法来获取控制器名称和操作? 有机会在核心中轻松做到这一点吗?
我有这样的东西:
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
}
}
我遇到了同样的问题,这在 .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()
之间调用您的中间件。在 Ganesh 的回答中我想添加一些条件。
AddControllers()
而不是AddMvc()
)UseRouting()
和 UseEndpoints()
之间调用您的中间件。否则
GetEndpoint()
返回 null。
这可行,但您需要确保在查询控制器和操作名称之前调用
_next(context)
。
public async Task InvokeAsync(HttpContext context)
{
await _next(context);
var controllerName = context.GetRouteData().Values["controller"];
var actionName = context.GetRouteData().Values["action"];
}
在 .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;
}
}
控制器和操作数据可通过过滤器获得,因此我以这种方式实现。控制器和操作数据在 ActionExecutingContext 对象中可用。
public class AsyncActionFilter : IAsyncActionFilter
{
public AsyncActionFilter(IEntityContext entityContext)
{
_entityContext = entityContext;
}
public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
//Handle the request
await next();
}
}
@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);
}