Get an instance of ActionFilterAttribute in a method

I am new to ASP.NET MVC platform, and I ran into the following problem.

I use ActionFilterAttribute to do the usual work before and after the action method runs. The problem is that I need to get an instance of the attribute in the action method in order to read some properties that were set in the OnActionExecuting method. for instance

public class SomeController : Controller{ public SomeController(){ } [Some] public ActionResult Index(){ SomeModel = someRepository.GetSomeModel(); //get instance of some attribute and read SomeProperty return View(SomeModel); } } public class SomeAttribute : ActionFilterAttribute{ public int SomeProperty { get; set; } public SomeAttribute(){ } public override void OnActionExecuting(ActionExecutingContext filterContext) { var parameters = filterContext.ActionParameters; //Here to set SomeProperty depends on parameters } public override void OnActionExecuted(ActionExecutedContext filterContext) { //do some work } } 

Any ideas?

+4
source share
3 answers

Filter attributes must be designed to ensure thread safety. The framework does not guarantee that one instance of your filter attribute will only serve one request at a time. Given this, you cannot mutate the state of an attribute instance from the OnActionExecuting / OnActionExecuted methods.

Consider one of the following options:

  • Use HttpContext.Items to store the value in OnActionExecuting, and then read it from the action method. You can access the HttpContext using the filterContext parameter passed to OnActionExecuting.

  • Place the property on the controller instead of the attribute, then include the OnActionExecuting method in the SomeController controller and set the property directly from this method. This will work as the default infrastructure ensures that controller instances are temporary; one controller instance will never serve more than one request.

+2
source

Sorry, I do not think this is possible. Since the value of SomeProperty should be based on the parameters sent to the attribute constructor, it needs to be easily calculated. I would suggest adding some static methods to get the value from within the action.

0
source

Option 1: your ActionFilter can add information to the ViewModel , for example

  filterContext.Controller.ViewData["YourKey"] = "Value to add"; 

Option 2: you can put the code in your base class Controller , which will find all the attributes that were applied to the executable method, and you can put them in a member variable that the Action method can use.

eg.

  protected override void OnActionExecuting(ActionExecutingContext filterContext) { var attrs = filterContext.ActionDescriptor.GetCustomAttributes(true).OfType<Some>(); ... } 

Edit: And, as others have noted, trying to change an attribute will not work.

0
source

All Articles