在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]
}
答案 0 :(得分:3)
您可以自定义FilterAttributeFilterProvider
和ActionFilterAttribute
来实现它。
首先,您可以创建一个继承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...
}
}