2012-03-13 77 views
6

我读过的一定数量的点出文章如何做到这一点,即:喷吹类为验证属性使用Unity 2和MVC 3

Stack overflow solution

Brad Wilsons excellent tutorial

这些似乎的确工作得很好,但是当我遵循的一些准则从这里

Securing your ASP.NET MVC 3 Application

我似乎来了一个收割机。对我来说,问题是我将我的AuthorizationAttribute添加为GlobalFilter,而不是仅仅装饰控制器/操作。尽管依赖解析器似乎被调用,并且在我重写AuthorizeAttribute的OnAuthorization()方法的代码的实际部分中设置公开的[Dependancy]属性时,我的public [Dependency]属性为null。

当我从全局过滤器中删除它并装饰一个控制器,它似乎工作。

如果需要更多信息,我可以发布代码。

编辑: 要在此位置进一步扩大是我的一些代码:

的global.asax.cs

public static void RegisterGlobalFilters(GlobalFilterCollection filters) 
    {       
     // If I have this here the my [Dependency] attribute does not keep it's value 
     // If I remove it and decorate the controller the [Dependency] attribute keeps it value 
     filters.Add(new BasicAuthenticationAttribute()); 
     filters.Add(new HandleErrorAttribute()); 
    } 

protected void Application_Start() 
    { 
     AreaRegistration.RegisterAllAreas(); 

     RegisterGlobalFilters(GlobalFilters.Filters); 
     RegisterRoutes(RouteTable.Routes); 

     // injection of services and data contexts 
     var container = new UnityContainer(); 

     // injections for services 
     RegisterUnityServices(container); 

     // Filter provides to allow injection into attribute filters 
     RegisterUnityFilters(container); 

    } 

    private void RegisterUnityServices(UnityContainer container) 
    { 
     container.RegisterType<IDataContext, CDAXDataContext>(); 

     container.RegisterType<IUploadService, UploadService>(); 
     container.RegisterType<IAuthenticationService, AuthenticationService>(); 

     // add more services here ...    
     DependencyResolver.SetResolver(new Models.UnityDependencyResolver(container));    
    } 

    private void RegisterUnityFilters(UnityContainer container) 
    { 
     var oldProvider = FilterProviders.Providers.Single(f => f is FilterAttributeFilterProvider); 
     FilterProviders.Providers.Remove(oldProvider); 

     var provider = new UnityFilterAttributeFilterProvider(container); 
     FilterProviders.Providers.Add(provider);    
    } 
从布拉德·威尔逊的例子采取

我统一类:

public class UnityDependencyResolver : IDependencyResolver 
{ 
    readonly IUnityContainer _container; 

    public UnityDependencyResolver(IUnityContainer container) 
    { 
     this._container = container; 
    } 

    public object GetService(Type serviceType) 
    { 
     try 
     { 
      return _container.Resolve(serviceType); 
     } 
     catch 
     { 
      return null; 
     } 
    } 

    public IEnumerable<object> GetServices(Type serviceType) 
    { 
     try 
     { 
      return _container.ResolveAll(serviceType); 
     } 
     catch 
     { 
      return new List<object>(); 
     } 
    } 
} 

And

public class UnityFilterAttributeFilterProvider : FilterAttributeFilterProvider 
{ 
    private IUnityContainer _container; 

    public UnityFilterAttributeFilterProvider(IUnityContainer container) 
    { 
     _container = container; 
    } 

    public override IEnumerable<Filter> GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor) 
    { 
     var filters = base.GetFilters(controllerContext, actionDescriptor); 

     foreach (var filter in filters) 
     { 
      _container.BuildUp(filter.Instance); 
     } 

     return filters; 
    } 

    protected override IEnumerable<FilterAttribute> GetControllerAttributes(
       ControllerContext controllerContext, 
       ActionDescriptor actionDescriptor) 
    { 

     var attributes = base.GetControllerAttributes(controllerContext, 
                 actionDescriptor); 
     foreach (var attribute in attributes) 
     { 
      _container.BuildUp(attribute.GetType(), attribute); 
     } 

     return attributes; 
    } 

    protected override IEnumerable<FilterAttribute> GetActionAttributes(
       ControllerContext controllerContext, 
       ActionDescriptor actionDescriptor) 
    { 

     var attributes = base.GetActionAttributes(controllerContext, 
                actionDescriptor); 
     foreach (var attribute in attributes) 
     { 
      _container.BuildUp(attribute.GetType(), attribute); 
     } 

     return attributes; 
    } 
} 

而My BasicAuthenticationAttribute的基础是我设置了[Dependency]属性,但是当方法被触发时并没有保持这个值。

public class BasicAuthenticationAttribute : AuthorizeAttribute 
{ 
    [Dependency] 
    public IAuthenticationService Authentication { get; set; } 

    private void CacheValidateHandler(HttpContext context, object data, ref HttpValidationStatus validationStatus) 
    { 
     validationStatus = OnCacheAuthorization(new HttpContextWrapper(context)); 
    } 

    public override void OnAuthorization(AuthorizationContext filterContext) 
    { 
     // code here that uses the Authentication attribute but it's null 
    } 

回答

3

你解决了吗? 我认为你需要调用属性类中的DependencyResolver ...不知道[Dependency]属性是否适用于此...所以在OnAuthorization方法调用IAuthenticationService authentication = DependencyResolver.Current.GetService<IAuthenticationService>();

+0

不,我没有。我觉得奇怪的是,如果我装饰控制器,但它不起作用,如果我把它放在global.ascx中。我会给你的方法去,但我真的希望通过使用Unity实现DIP。目前它正在工作,但解释方法是我装饰控制器,而不是将其包含在全局文件中。 – dreza 2012-04-20 19:52:09

+0

我发现了相同的行为,在控制器中工作正常,但没有在属性/过滤器中...它只是不在那里,所以我需要调用DependencyResolver。来自http://stackoverflow.com/users/759701/ethan-cabiac的有趣评论“它不是关于它们是否被注册,而是关于它们是如何实例化的。本质上,框架调用新的Authenticate(),绕过任何DI容器“在这个问题http://stackoverflow.com/questions/6121050/mvc-3-unity-2-inject-dependencies-into-a-filter – w4ik 2012-04-20 20:36:01