我遇到了Action Filters和Autofac的问题。我有一个动作过滤器,它使用依赖项来确定是否应该重定向请求。我明确地将此过滤器应用于一组控制器操作。重定向将指向未应用此过滤器的操作。但是,过滤器仍会触发,最终会无限循环。
请注意,下面的代码是正在进行的一些逻辑的框架。我只是想捕捉到我遇到的问题。
在我的情况下,具有此属性的控制器是accound控制器中的内置。即登录操作。我已经设置了自动调整过滤器以应用于FitlerConfig.cs中的所有操作:
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new AuthorizeAttribute());
filters.Add(new HandleErrorAttribute());
}
我的过滤器看起来像这样:
public class CustomFilter : ActionFilterAttribute
{
public SomeDependancy MyDependancy { get; set; }
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (MyDependancy.ShouldRedirect)
{
filterContext.Result = new RedirectToRouteResult("Default",
new RouteValueDictionary
{
{ "controller", "Error" }, { "action", "CustomError" }
}
);
}
base.OnActionExecuting(filterContext);
return;
}
}
我的帐户管理员:
public class AccountController : Controller
{
[AllowAnonymous]
[CustomFilter]
public ActionResult Login(string returnUrl)
{
ViewBag.ReturnUrl = returnUrl;
return View();
}
}
错误控制器:
public class ErrorController : Controller
{
[AllowAnonymous]
public ActionResult CustomError()
{
return View("CustomError");
}
}
最后,我的autofac注册:
var builder = new ContainerBuilder();
builder.Register(con => new SomeDependancy()).AsSelf().InstancePerHttpRequest();
builder.RegisterType<CustomFilter>().As<IActionFilter>().PropertiesAutowired();
// property injection on filters
builder.RegisterFilterProvider();
// Needed to allow property injection in custom action filters.
builder.RegisterType<ExtensibleActionInvoker>().As<IActionInvoker>();
builder.RegisterControllers(typeof(MvcApplication).Assembly).InjectActionInvoker();
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
最终发生的事情是,如果我在CustomFilter中设置了一个断点,当我进入登录页面时,断点点击并发生重定向,然后断点再次点击,一次又一次点击。令我困惑的是,此动作过滤器未应用于该控制器或操作。
如果我注释掉依赖项并简单地在过滤器中重定向,然后注释掉autofac注册,那么事情就会按预期工作。点击登录屏幕后,过滤器会触发并重定向到错误页面。
答案 0 :(得分:2)
我发现了问题所在。
我查看了Autofac的ExtensibleActionInvoker的源代码。
我在它的构造函数中读到了一条评论:
/// The following types, if registered in the container, will be added to the
/// filters list:
/// <list>
/// <item><see cref="IActionFilter"/></item>
/// <item><see cref="IAuthorizationFilter"/></item>
/// <item><see cref="IExceptionFilter"/></item>
/// <item><see cref="IResultFilter"/></item>
/// </list>
为了解决我的问题,我最终得到了:
var builder = new ContainerBuilder();
builder.Register(con => new SomeDependancy()).AsSelf().InstancePerHttpRequest();
// builder.RegisterType<CustomFilter>().As<IActionFilter>().PropertiesAutowired();
// property injection on filters
builder.RegisterFilterProvider();
// Needed to allow property injection in custom action filters.
builder.RegisterType<ExtensibleActionInvoker>().As<IActionInvoker>();
builder.RegisterControllers(typeof(MvcApplication).Assembly).InjectActionInvoker();
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
事实证明,我不需要注册我的CustomFilter。这样做会导致ExtensibleActionInvoker自动注册为全局过滤器。