如何从 HttpContext 获取 ASP.NET Core MVC 过滤器

Posted

技术标签:

【中文标题】如何从 HttpContext 获取 ASP.NET Core MVC 过滤器【英文标题】:How to get ASP.NET Core MVC Filters from HttpContext 【发布时间】:2018-02-14 00:15:53 【问题描述】:

我正在尝试编写一些中间件,并且需要知道当前操作方法(如果有)是否具有特定的过滤器属性,因此我可以根据它的存在来更改行为。

那么当您实现IResourceFilter 时,是否可以像在ResourceExecutingContext 上那样获得IList<IFilterMetadata> 类型的过滤器集合?

【问题讨论】:

【参考方案1】:

今天真的不可能。

在 ASP.NET Core 3.0 中可以实现

app.UseRouting();


app.Use(async (context, next) =>

    Endpoint endpoint = context.GetEndpoint();

    YourFilterAttribute filter = endpoint.Metadata.GetMetadata<YourFilterAttribute>();

    if (filter != null)
     

    

    await next();
);


app.UseEndpoints(endpoints =>

    endpoints.MapControllers();
);

【讨论】:

现在可以在 ASP.NET Core 3.0 中实现吗?特别是,我有一个来自响应重写中间件的RewriteContext【参考方案2】:

注意:并不是真正直接回答您的问题,但可能会根据您的需要有所帮助(而且代码对于 cmets 来说太长了)

注意 2:不确定它是否适用于 Core,如果不适用,请告诉我,我会删除答案

您可以知道,在一个过滤器中,是否同时使用了另一个过滤器:

public class OneFilter : ActionFilterAttribute, IActionFilter

    void IActionFilter.OnActionExecuting(ActionExecutingContext filterContext)
    
        // Check if the Attribute "AnotherFilter" is used
        if (filterContext.ActionDescriptor.IsDefined(typeof(AnotherFilter), true) || filterContext.Controller.GetType().IsDefined(typeof(AnotherFilter), true))
        
            // things to do if the filter is used

        
    


public class AnotherFilter : ActionFilterAttribute, IActionFilter

   // filter things

与/或

你可以在Route数据中放一些数据,让Action知道使用了哪些Filters:

void IActionFilter.OnActionExecuting(ActionExecutingContext filterContext)

    filterContext.RouteData.Values.Add("OneFilterUsed", "true");
    base.OnActionExecuting(filterContext);

...

public ActionResult Index()

    if(RouteData.Values["OneFilterUsed"] == "true")
    

    

    return View();

【讨论】:

IsDefined 在 .Net Core 的 ActionDescriptor 中不存在。 是的,没有IsDefined(),但可以使用以下内容:if (filterContext.Filters.Any(x =&gt; filters.Contains(typeof(AnotherFilter)));) // 要做的事情... 【参考方案3】:

ASP.NET Core 3.0 使用一个新的路由,每个动作都是一个Endpoint,动作和控制器的所有属性都存在于Metadata

你可以这样做。

app.UseRouting();


app.Use(async (context, next) =>

    Endpoint endpoint = context.GetEndpoint();

    YourFilterAttribute filter = endpoint.Metadata.GetMetadata<YourFilterAttribute>();

    if (filter != null)
     

    

    await next();
);


app.UseEndpoints(endpoints =>

    endpoints.MapControllers();
);

【讨论】:

这与上一篇文章中的代码完全相同(您已对其进行编辑以包含该代码),因此现在是重复的答案

以上是关于如何从 HttpContext 获取 ASP.NET Core MVC 过滤器的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 IIS 从 Blazor 服务器获取 WindowsIdentity.RunImpersonated(token, action) 的 HttpContext(或 AccessToken)

如何在 ASP.NET Core 中获取 HttpContext.Current? [复制]

从ActionExecutingContext获取原始端口?

从 HTTP POST 获取查询字符串?

如何在不使用 HttpContext 的情况下获取 Web 应用程序的当前配置?

数据项目中的 MVC 5 HttpContext.User