Here is a sample action filter. We know that when we write an action filter then we need to decorate the controller with an attribute like this, to use it for any controller.
I like to know whether there is any way to write an action filter which will work for all controllers in way that I do not need to decorate all the controllers with an action filter attribute. Any ideas?
[LogActionFilter]
public class HomeController : Controller
{}
public class LogActionFilter : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
Log("OnActionExecuting", filterContext.RouteData);
}
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
Log("OnActionExecuted", filterContext.RouteData);
}
private void Log(string methodName, RouteData routeData)
{
var controllerName = routeData.Values["controller"];
var actionName = routeData.Values["action"];
var message = String.Format("{0} controller:{1} action:{2}", methodName, controllerName, actionName);
Debug.WriteLine(message, "Action Filter Log");
}
}
Action Filters − Action filters are used to implement logic that gets executed before and after a controller action executes.
Right-click on Controllers, select "Add" and click on "Controller". Select "Web API 2 Controller with read/write actions" and click the "Add" button. Name it "Home Controller". It will add a controller with 5 API methods.
If you need, you can apply multiple action filters to the same action. For example, you might want to apply both the OutputCache and HandleError action filters to the same action.
If you're already subclassing from a base controller, you don't need a filter attribute or to register anything. You can just override the desired methods, e.g.,
public class BaseController : Controller {
protected override void OnActionExecuting(ActionExecutingContext filterContext) {
ViewBag.SomeValue = "glorp frob blizz nunk";
// Access the controller, parameters, querystring, etc. from the filterContext
base.OnActionExecuting(filterContext);
}
}
Then, every controller that subclasses from it will run that method:
public sealed class GlorpController : BaseController {
public ActionResult Index() => View();
}
The view will quite happily see the ViewBag.SomeValue
value.
public class LogActionFilterAttribute : IActionFilter
{
public void OnActionExecuted(ActionExecutedContext filterContext)
{
Log("OnActionExecuted", filterContext.RouteData);
}
public void OnActionExecuting(ActionExecutingContext filterContext)
{
Log("OnActionExecuting", filterContext.RouteData);
}
private void Log(string methodName, RouteData routeData)
{
var controllerName = routeData.Values["controller"];
var actionName = routeData.Values["action"];
var message = String.Format("{0} controller:{1} action:{2}", methodName, controllerName, actionName);
Debug.WriteLine(message, "Action Filter Log");
}
}
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
GlobalFilters.Filters.Add(new LogActionFilterAttribute());
}
}
For your scenario you can just make a Custom BaseController and put your [LogActionFilter]
attribute on Custom Basecontroller and inherit all your Controllers from Custom Basecontroller as shown below :
[LogActionFilter]
public class MyBaseController : Controller
{
}
public class MyOtherController : MyBaseController //<----instead of using Controller as base use MyBaseController as base class
{
public ActionResult Index()
{
// ...
}
}
The advantage of this approach is that you have to put your custom [LogActionFilter]
attribute only at one place i.e. only on Custom BaseController.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With