How to get ASP.NET Core MVC Filters from HttpContext

5.2k views Asked by At

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?

3

There are 3 answers

1
davidfowl On BEST ANSWER

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();
});
2
Matthieu Charbonnier On

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();
}
1
Kahbazi On

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();
});