views:

23

answers:

3

I am newbie in ASP.NET MVC platform and I faced with the following problem.

I am using ActionFilterAttribute to do some routine work before and after action method run. The problems is that I need to get instance of the attribute in action method to read some properties which was set in OnActionExecuting method. For example

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?

A: 

Sorry, I do not believe this is possible. Since the value of SomeProperty must be based on parameters sent into the constructor of the attribute, it must be easy to calculate. I would suggest adding some static methods to get the value from within the action.

Brian
A: 

Option 1: Your ActionFilter can add information to the ViewModel, e.g.

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

Option 2: You can put code in your base Controller class that finds all the attributes that have been applied to the method that is executing, and you can put them in a member variable that the Action method can then use.

e.g.

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

Edit: And as others have noted, trying to mutate the attribute isn't going to work.

Hightechrider
A: 

Filter attributes must be designed to be thread-safe. The framework makes no guarantees that a single instance of your filter attribute will only service one request at a time. Given this, you cannot mutate attribute instance state from within the OnActionExecuting / OnActionExecuted methods.

Consider one of these as alternatives:

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

  • Put the property on the controller instead of the attribute, then have the OnActionExecuting method cast the controller to SomeController and set the property directly from within that method. This will work since the framework does by default guarantee that controller instances are transient; a single controller instance will never service more than one request.

Levi