Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I intercept all controller calls in an MVC application?

Is there a quick method for intercepting all controller calls in MVC-3?

For logging and testing purposes, I'd like to build a tool that can intercept all controller calls, and log which controller was called, with which message, at what time.

like image 412
blueberryfields Avatar asked Feb 21 '12 19:02

blueberryfields


People also ask

Can we overload methods of a controller in MVC?

If we have to overload the action Method in asp.net MVC then we can not do it directly. We have to change the ActionName like this code snippet. Now to run the controller GetEmpName action method with just give the URL like this: http://localhost:49389/Home/GetEmpName.

Can we use constructor in MVC controller?

ASP.NET Core MVC controllers request dependencies explicitly via constructors.


4 Answers

I can't remember where I got this from, but I was looking around for something similar a while back and found an article or something somewhere that contained this logging filter:

public class LogActionFilter : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        Log("OnActionExecuting", filterContext.RouteData);
    }

    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        Log("OnActionExecuted", filterContext.RouteData);
    }

    public override void OnResultExecuting(ResultExecutingContext filterContext)
    {
        Log("OnResultExecuting", filterContext.RouteData);
    }

    public override void OnResultExecuted(ResultExecutedContext filterContext)
    {
        Log("OnResultExecuted", 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");
    }
}

To use it, just add it to the global filters in global.asax:

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
    filters.Add(new HandleErrorAttribute());
    filters.Add(new LogActionFilter());
}

I'll have a look now to see if I can find the source.

Edit: Found it. It was from this question.

like image 132
John H Avatar answered Oct 01 '22 15:10

John H


Depending on how big the site is already, you could create a class in the hierarchy between the framework's Controller class and your main controllers.

Something like

public class MyBaseController : Controller {
    protected override void OnActionExecuting(ActionExecutingContext filterContext) {
        // your logging stuff here
        base.OnActionExecuting(filtercontext);
    }
}

Then the rest of your controllers can inherit from this, e.g.

public class HomeController : MyBaseController {
    // action methods...
}
like image 32
Dave Avatar answered Oct 01 '22 15:10

Dave


You can use your own controller factory and register it as well: From: (many example on the net - insert logging where you want)

adapted from: http://www.keyvan.ms/custom-controller-factory-in-asp-net-mvc

using System;
using System.Configuration;
using System.Web.Mvc;
using System.Web.Routing;

namespace IControllerFactorySample.ControllerFactories
{
    public class YourControllerFactory : IControllerFactory
    {
        #region IControllerFactory Members

        public IController CreateController(RequestContext requestContext, string controllerName)
        {
            if (string.IsNullOrEmpty(controllerName))
                throw new ArgumentNullException("controllerName");

            IController controller = Activator.CreateInstance(Type.GetType(controllerName)) as IController;

            return controller;
        }

        public void ReleaseController(IController controller)
        {
            if (controller is IDisposable)
                (controller as IDisposable).Dispose();
            else
                controller = null;
        }

        #endregion
    }
}

dont forget to register it in global.asax.cs

ControllerBuilder.Current.SetControllerFactory(
                typeof(YourControllerFactory));
like image 2
Adam Tuliper Avatar answered Oct 01 '22 14:10

Adam Tuliper


there is a routing debugger developed by Phil Haack

ASP.Net Routing Debugger

like image 1
Rafay Avatar answered Oct 01 '22 13:10

Rafay