2012-03-13 53 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