【问题标题】:Help with action filters in asp.net mvc 3帮助 asp.net mvc 3 中的操作过滤器
【发布时间】:2011-08-10 16:09:49
【问题描述】:

我想创建一个操作过滤器,仅由我的应用程序中的两个控制器使用...这个操作过滤器应该检查两个控制器内的每个操作。

这是我的操作过滤器代码

public class AllowedToEditEHRFilter : IActionFilter
    {
        IUnitOfWork unitOfWork;
        IRepository<EHR> ehrRepository;
        public AllowedToEditEHRFilter(IUnitOfWork dependency)
        {
            unitOfWork = dependency;
            ehrRepository = unitOfWork.EHRs;
        }

        public void OnActionExecuting(ActionExecutingContext filterContext)
        {
            int ehrId;
            if (int.TryParse(filterContext.HttpContext.Request.QueryString["ehrId"], out ehrId))
            {
                EHR ehr = ehrRepository.FindById(ehrId);
                if (ehr.UserName != Membership.GetUser().UserName)
                    filterContext.Result = new ViewResult { ViewName = "InvalidOwner" };
            }
        }
        public void OnActionExecuted(ActionExecutedContext filterContext)
        {

        }
    }

现在我只是不确定如何配置 MVC 框架,以便在适当的时间触发操作过滤器。

我使用this 作为参考,但它应用了一个 GLOBAL 动作过滤器,它没有指定如何仅限于你的一些控制器。

请帮忙。

顺便说一句,我正在使用 NinjectMVC3

【问题讨论】:

    标签: asp.net-mvc asp.net-mvc-3 ninject action-filter


    【解决方案1】:

    这取决于合适的时间。

    查看我原来的博文

    或者阅读文档的其他页面:

    (可能我应该链接它们)

    基本上你需要为过滤器配置一个绑定并定义一些条件:

    kernel.BindFilter<AllowedToEditEHRFilter>(FilterScope.Action, 0).When...
    

    例如

    .WhenActionHas<AllowedToEditEHRAttribute>()
    

    更新: 在你的情况下简单

    kernel.BindFilter<AllowedToEditEHRFilter>(FilterScope.Controller, 0).When(
        (controllerContext, actionDescriptor) =>  
         controllerContext.Controller is PhysicalTestsController)
    

    【讨论】:

    • 一个快速的问题..说我想将它用于另一个控制器... LabTests Controller...我应该复制绑定并将 PhysicalTestsController 更改为 LabTestsController 还是有一种方法来定义同一命令中的所有条件?
    • 只需将您传递给WhenFunc 更改为两个控制器都返回true。或者更改为WhenControlerHas&lt;SomeAttribute&gt; 并将该属性添加到要应用此属性的所有控制器。阅读文档了解更多信息。
    【解决方案2】:

    要将动作过滤器仅应用于某些控制器,只需将属性添加到相关控制器即可。

    [AllowedToEditEHR]
    public class YourController : Controller
    {
        ...
    

    为此,您应该将过滤器重命名AllowedToEditEHRAttribute,即将“过滤器”替换为“属性”。这是属性的标准命名约定。

    更新:要在过滤器中注入依赖项,只需使用[Inject] 属性装饰它的构造函数即可。

    【讨论】:

    • 是的,这是一种方式,我很欣赏你的回答......但是,取自 ninject wiki 本身“虽然仍然支持注入过滤器属性,但建议使用这种新模式进行过滤器配置,因为它的优点是支持构造函数注入,不再需要 InjectAttribute。"
    • -1 不能对属性进行构造函数注入,因为它们不是由 ninject 创建的,而是由 .NET Framework 创建的。因此,使用属性不是依赖注入的好方法。
    【解决方案3】:
    public class AllowedToEditEHRFilter : IActionFilter
        {
            IUnitOfWork unitOfWork;
            IRepository<EHR> ehrRepository;
    
            public AllowedToEditEHRFilter(IUnitOfWork dependency)
            {
                unitOfWork = dependency;
                ehrRepository = unitOfWork.EHRs;
            }
    
            public void OnActionExecuting(ActionExecutingContext filterContext)
            {
                int ehrId;
                if (int.TryParse(filterContext.ActionParameters["ehrId"].ToString(), out ehrId))
                {
                    EHR ehr = ehrRepository.FindById(ehrId);
                    if (ehr.UserName != Membership.GetUser().UserName)
                        filterContext.Result = new ViewResult { ViewName = "InvalidOwner" };
                }
            }
            public void OnActionExecuted(ActionExecutedContext filterContext)
            {
    
            }
        }
    

    还有 CustomFilterProvider

    public class ConfiguredFilterProvider : IFilterProvider
        {
            private readonly IKernel _kernel;
    
            public ConfiguredFilterProvider(IKernel kernel)
            {
                _kernel = kernel;
            }
    
            public IEnumerable<Filter> GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
            {
                List<Filter> list = new List<Filter>();
                if (controllerContext.Controller is PhysicalTestsController)
                {
    
                    list.Add(new Filter(
                                _kernel.Get(typeof(AllowedToEditEHRFilter)),
                                FilterScope.Global, order: null
                            ));
                }
                return list;
            }
        }
    

    在 Ninject 中

    kernel.Bind<IFilterProvider>()
                  .To<ConfiguredFilterProvider>();
    

    它可能不是最干净的解决方案,但它的工作原理。

    【讨论】:

    • 如果 Ninject.MVC3 扩展有更强大的实现,为什么还要重新发明轮子?
    • 一个简单的绑定也是如此:kernel.BindFilter(FilterScope.Controller, 0).When((controllerContext, actionDescriptor) => controllerContext.Controller is PhysicalTestsController)
    • 我安装了 NinjectMVC3 nuget 包,但似乎根本没有 BindFilter 方法...:s
    • 没关系,我只需要添加 Ninject.Web.Mvc.FilterBindingSyntax 命名空间!...它工作得很好。
    【解决方案4】:

    你只需要像这样用动作过滤器装饰那两个控制器

    [AllowedToEditEHRFilter]
    public class YourController : Controller
    {
        ...
    }
    

    但是,我不确定是否允许在该过滤器的构造函数中传递复杂对象。

    【讨论】:

      【解决方案5】:

      不要实现IActionFilter,而是扩展ActionFilterAttribute,然后将属性分配给您想要影响的两个控制器:

      public class AllowedToEditEHRFilter : ActionFilterAttribute
      {
          // ...
      }
      

      和:

      [AllowedToEditEHRFilter]
      public class MyController : Controller
      {
          // ...
      }
      

      【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多