是否可以从每个请求调用一个方法

时间:2015-04-07 13:24:19

标签: c# asp.net asp.net-mvc

我正在开发一个asp.net MVC项目。我们想以这种方式记录所有的动作方法调用:

namespace.controller.method(parameter1name: parameter1value, ... parameternname: parameternvalue)

这在C#或带有属性的asp.net MVC中是否可行?我的想法是ActionFilterAttribute,但据我了解,在调用实际方法之前调用它们。

更多细节,为什么ActionFilterAttribute在这种情况下不起作用。我们希望使用完整的.net命名空间,类名,原始方法名和所有参数来记录方法调用。

这是一个例子

namespace MyTestNamespace {

    public class HomeController {

        [ActionName("Index")]
        [HttpGet]
        public ActionResult MyCall(string username) {
            ViewBag.Great = "Hello " + username;
            return View();
        }
    }
}

日志记录输出应如下所示:

MyTestNamespace.HomeController.MyCall(username: Knerd)

但我可以使用ActionFilterAttribute得到的日志输出是这样的:

MyTestNamespace.HomeController.Index(username: Knerd)

1 个答案:

答案 0 :(得分:3)

您可以在动作过滤器中恢复大部分(如果不是全部)此类信息。这里唯一缺少的可能是命名空间,但你应该能够通过访问filterContext.Controller对象并对其进行一些反思来找到它。

public class MyFilter : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        var controllerName = routeData.Values["controller"];
        var actionName = routeData.Values["action"];

        foreach(var kvp in filterContext.ActionParameters)
            //log your params

        //thanks @Andy Nichols
        var fullControllerName = filterContext.ActionDescriptor.ControllerDescriptor.ControllerType.FullName;
    }
}

在大多数情况下,路线的名称应与方法的名称相匹配。如果没有,您可以为这些路由映射设置某种全局注册表。

以下是如何执行此操作的示例。你在这里失去了一些路由可配置性,但你可以扩展它以允许它。

public static class RouteMappingConfig
{
    static RouteMappingConfig () { RouteMappings = new List<RouteMapping>(); }
    public static List<RouteMapping> RouteMappings { get; set; }
}
public class RouteMapping
{
    public class RouteMapping(string ctrl, string action, string method) { /*...*/ }
    public string Controller { get; set; }
    public string Action { get; set; }
    public string Method { get; set; }
}

public class RouteConfig
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        //set up mappings
        RouteMappingConfig.RouteMappings.Add(new RouteMapping("MyController", "MyAction", "MyMethod"));

        foreach(var mapping in RouteMappingConfig.RouteMappings)
        {
            routes.MapRoute(
                name: mapping.Controller + "_" + mapping.Action,
                url: "{controller}/{action}/",
                defaults: new { controller = mapping.Controller, action = mapping.Action }
            );
        }
    }
}

public class MyFilter : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        var controllerName = routeData.Values["controller"];
        var actionName = routeData.Values["action"];

        //thanks @Andy Nichols
        var fullControllerName = filterContext.ActionDescriptor.ControllerDescriptor.ControllerType.FullName;
        var mapping = RouteMappingConfig.RouteMappings.SingleOrDefault(x => x.Controller == controllerName && x.Action == actionName);
        string methodName = actionName;
        if(mapping != null)
        {
            methodName = mapping.Method;
        }

        foreach(var kvp in filterContext.ActionParameters)
            //log your params

    }
}