How to get ASP.NET Core MVC Filters from HttpContext
Asked Answered
S

3

6

I'm trying to write some middleware and need to know if the current action method (if any) has a particular filter attribute, so I can change behaviour based it's existence.

So is it possible to get a filters collection of type IList<IFilterMetadata> like you do on the ResourceExecutingContext when you are implementing an IResourceFilter?

Scorper answered 5/9, 2017 at 16:15 Comment(0)
D
11

It's not really possible today.

It is possible in 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();
});
Deferment answered 6/9, 2017 at 6:55 Comment(1)
Is this now possible in ASP.NET Core 3.0? In particular, I have a RewriteContext from the response rewrite middleware.Scorper
J
5

ASP.NET Core 3.0 uses a new routing which every action is an Endpoint and all attributes on the action and the controller exists on Metadata.

Here's how you can do it.

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();
});
Jericajericho answered 18/10, 2019 at 21:28 Comment(1)
This is the same exact code from the prior post (which you edited to contain that) so is now a duplicate answerStricture
V
0

Note: Not really answering directly your question, but may help depending of your needs (and the code is too long for comments)

Note 2: Not sure if it works on Core, if it doesn't, tell me and I remove the answer

You can know, in a filter, if another filter is used along with:

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
}

AND/OR

You can put some data in the Route data to let know the Action which Filters are used:

void IActionFilter.OnActionExecuting(ActionExecutingContext filterContext)
{
    filterContext.RouteData.Values.Add("OneFilterUsed", "true");
    base.OnActionExecuting(filterContext);
}

...

public ActionResult Index()
{
    if(RouteData.Values["OneFilterUsed"] == "true")
    {

    }

    return View();
}
Valentino answered 6/9, 2017 at 7:11 Comment(2)
IsDefined doesn't exist in .Net Core's ActionDescriptor.Kuykendall
Yeap, there is no IsDefined(), but the following can be used: if (filterContext.Filters.Any(x => filters.Contains(typeof(AnotherFilter)));) { // things to do... }Calf

© 2022 - 2024 — McMap. All rights reserved.