How can I intercept all controller calls in an MVC

2020-05-26 02:26发布

问题:

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.

回答1:

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.



回答2:

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...
}


回答3:

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));


回答4:

there is a routing debugger developed by Phil Haack

ASP.Net Routing Debugger