如何从OnResultExecuted中获取ActionDescription UniqueId

时间:2015-05-22 02:24:27

标签: asp.net-mvc

在ASP.NET MVC中,有没有人知道从OnResultExecuted中访问ActionDescriptor.UniqueId的技巧?我需要以一种方式将OnActionExecuting中的信息传递给OnResultExecuted,如果在一个HttpRequest期间执行了多个操作,那么该方法将起作用。

例如:

private Dictionary<string,Foo> _foos
{
    get { return HttpContext.Current.Items["foos"] as Dictionary<string,Foo>; }
    set { HttpContext.Current.Items["foos"] = value; }
}

public override void OnActionExecuting(ActionExecutingContext context)
{
    var foos = _foos;
    foos[context.ActionDescriptor.UniqueId] = new Foo();
    _foos = foos;
}

public override void OnResultExecuted(ResultExecutedContext context)
{
    var actionUniqueId = ????
    var foo = _foos[actionUniqueId]
}

1 个答案:

答案 0 :(得分:3)

您可以自定义FilterAttributeFilterProviderActionFilterAttribute来实现它。

首先,您可以创建一个继承ActionFilterAttribute且包含ActionDescriptor属性的过滤器:

public class MyActionFilterAttribute : ActionFilterAttribute
{
    public ActionDescriptor ActionDescriptor { get; set; }

    public override void OnResultExecuted(ResultExecutedContext filterContext)
    {
        var actionUniqueId = ActionDescriptor.UniqueId;

        //code..
    }
}

然后,您需要创建过滤器提供程序继承FilterAttributeFilterProvider并覆盖GetFilters方法:

public class MyFilterProvider : FilterAttributeFilterProvider
{
    public override IEnumerable<Filter> GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
    {
        if (controllerContext.Controller != null)
        {
            foreach (FilterAttribute attr in GetControllerAttributes(controllerContext, actionDescriptor))
            {
                var myAttr = attr as MyActionFilterAttribute;
                if (myAttr != null) 
                {
                    myAttr.ActionDescriptor = actionDescriptor;
                }

                yield return new Filter(attr, FilterScope.Controller, order: null);
            }
            foreach (FilterAttribute attr in GetActionAttributes(controllerContext, actionDescriptor))
            {
                var myAttr = attr as MyActionFilterAttribute;
                if (myAttr != null)
                {
                    myAttr.ActionDescriptor = actionDescriptor;
                }

                yield return new Filter(attr, FilterScope.Action, order: null);
            }
        } 
    }
}

您可以在GetFilters方法中看到,如果过滤器类型为ActionDescriptor,我们会设置MyActionFilterAttribute属性。

最后,在Global.asax,您需要使用MyFilterProvider实例替换Providers集合中的FilterAttributeFilterProvider实例:

public class MvcApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        //replace the FilterAttributeFilterProvider in providers collection
        for (int i = 0; i < FilterProviders.Providers.Count; i++)
        {
            if (FilterProviders.Providers[i] is FilterAttributeFilterProvider)
            {
                FilterProviders.Providers[i] = new MyFilterProvider();
                break;
            }
        }

        //other global init code...
    }
}