27

I have a controller in my MVC app for which I'm trying to log details using a custom ActionFilterAttribute, by using the onResultExecuted method.

I read this tutorial to understand and write my own action filter. The question is how do I pass variables from the controller to the action filter?

  1. I want to get the input variables with which a controller is called. Say, the username/user ID.
  2. If (in some situations) an exception is thrown by any controller method, I would want to log the error too.

The controller -

[MyActionFilter]
public class myController : ApiController {
    public string Get(string x, int y) { .. }
    public string somemethod { .. }
}

The action filter -

public class MyActionFilterAttribute : ActionFilterAttribute {
    public override void onActionExecuted(HttpActionExecutedContext actionExecutedContext) {
        // HOW DO I ACCESS THE VARIABLES OF THE CONTROLLER HERE
        // I NEED TO LOG THE EXCEPTIONS AND THE PARAMETERS PASSED TO THE CONTROLLER METHOD
    }
}

I hope I have explained the problem here. Apologies if I'm missing out some basic objects here, I'm totally new to this.

Imad Alazani
  • 6,688
  • 7
  • 36
  • 58
divyanshm
  • 6,600
  • 7
  • 43
  • 72

2 Answers2

75

Approach - 1

Action Filter

public class MyActionFilter : ActionFilterAttribute
{
    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        base.OnActionExecuted(filterContext);
    }
}

Action Method

[MyActionFilter]
public ActionResult Index()
{
    ViewBag.ControllerVariable = "12";
    return View();
}

enter image description here

If you pay attention to the screenshot, you can see the ViewBag information

Approach - 2

Action Filter

public class MyActionFilter : ActionFilterAttribute
{
    //Your Properties in Action Filter
    public string Property1 { get; set; }
    public string Property2 { get; set; }

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        base.OnActionExecuting(filterContext);
    }
}

Action Method

[MyActionFilter(Property1 = "Value1", Property2 = "Value2")]
public ActionResult Index()
{
    return View();
}
Imad Alazani
  • 6,688
  • 7
  • 36
  • 58
  • I had been busy with something else, just got this thing working for me. Thank you PKKG! :) – divyanshm Aug 19 '13 at 05:37
  • @divyanshm : That's great. – Imad Alazani Aug 19 '13 at 05:38
  • 1
    Okay, So I just realized that variables are not being passed using ViewBag. In my project controller C1 calls c2, which calls C3. I'm doing this for C2, which doesn't exactly have a view with it. How can I access variables in this case. – divyanshm Aug 19 '13 at 06:11
  • How would you retrieve the value from filterContext.Controller.ViewBag > DynamicView > ControllerVariable ? – Mohammad S. May 04 '17 at 08:41
  • 1
    @Ovis use `var mystring = filterContext.Controller.ViewBag.MyViewbagThing;` – Mark Schultheiss Aug 25 '17 at 13:14
  • The value in the viewbag will not be available in OnActionExecuting because the the OnActionExecuting will be executed prior. The best possible solution will be to have the ViewBag value inside OnActionExecuted(). – Jyo Oct 11 '17 at 14:05
  • I'm using Approcha2, but once the ControllerA get executed, it overrides global values (this filter is also globaly registered), so the ControllerB has actually ControllerA values, not global ones that I need. Is there any workaround for this problem? – Akbari Dec 05 '17 at 08:33
  • I created a pair of get and set static helpers for the TempData class to make is simple to add (in my case one string to one fixed key) within the action. Temp data should be available across all actions. If you are going to set values in different actions them add multiple keys to temp data or a generic list, and add values to that list, such as a fixed class that indicates which controller and action the value came from –  Apr 27 '18 at 12:13
  • I want to pass a String Method like GetUserName() as parameter, but it only accept the hard coded value like "UserName" etc... in approach 2. What to do in this case. – Zia Ur Rahman Feb 19 '21 at 08:23
0

I suggest another approach, and it is passing parameters to Action Filter as constractor.

[PermissionCheck(Permissions.NewUser)]
public ActionResult NewUser()
{
 // some code
}

Then in the ActionFilter:

public class PermissionCheck : ActionFilterAttribute
{
    public Permissions Permission { get; set; }
    public PermissionCheck(Permissions permission)
    {
        Permission = permission;
    }
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        
        
        if (/*user doesn't have that permission*/)
        {

            filterContext.Result = new RedirectToRouteResult
           (
               new RouteValueDictionary
                   (
                       new {
                           controller = "User",
                           action = "AccessDeny",
                           error = "You don't have permission to do this action"
                       }
                   )
           );
            base.OnActionExecuting(filterContext);
        }
    }
}

Which Permissions is an ENUM like:

enum Permissions {NewUser, Edit, Delete, Update, ...}
Peyman Majidi
  • 1,777
  • 2
  • 18
  • 31