12

Tôi đang cố gắng giải quyết các phụ thuộc của tùy chỉnh AuthorizeAttribute tùy chỉnh mà tôi sử dụng để trang trí bộ điều khiển API của mình trong ứng dụng MVC4. Vấn đề là tôi tiếp tục nhận được một NullReferenceException về sự phụ thuộc dịch vụ mà tôi sử dụng trong bộ lọc tùy chỉnh của mình. Dưới đây là cấu hình của tôi Autofac:Tiêm phụ thuộc vào thuộc tính bộ lọc hành động API Web tùy chỉnh với Autofac

public static class WebApiConfig 
{ 
    public static void Register(HttpConfiguration config) 
    { 
     var builder = new ContainerBuilder(); 
     builder.RegisterApiControllers(Assembly.GetExecutingAssembly()); 
     builder.RegisterType<UnitOfWork>().As<IUnitOfWork>().InstancePerApiRequest(); 
     builder.RegisterType<DatabaseFactory>().As<IDatabaseFactory>().InstancePerApiRequest(); 
     builder.RegisterAssemblyTypes(typeof(UserProfileRepository).Assembly) 
      .Where(t => t.Name.EndsWith("Repository")) 
      .AsImplementedInterfaces().InstancePerApiRequest(); 

     builder.RegisterAssemblyTypes(typeof(IUserProfileMapper).Assembly) 
      .Where(t => t.Name.EndsWith("Mapper")) 
      .AsImplementedInterfaces().InstancePerApiRequest(); 

     builder.RegisterAssemblyTypes(typeof(UserProfileSvc).Assembly) 
      .Where(t => t.Name.EndsWith("Svc")) 
      .AsImplementedInterfaces().InstancePerApiRequest(); 

     builder.RegisterWebApiFilterProvider(config); 
     var container = builder.Build(); 
     var resolver = new AutofacWebApiDependencyResolver(container); 
     config.DependencyResolver = resolver; 
    } 
} 

và tùy chỉnh của tôi ủy quyền cho bộ lọc:

public class MyAuthorizeAttribute : AuthorizeAttribute 
{ 
    public IAuthenticationSvc _authenticationSvc; 
    protected override bool IsAuthorized(System.Web.Http.Controllers.HttpActionContext actionContext) 
    { 
     if (!base.IsAuthorized(actionContext)) 
     { 
      return false; 
     } 
     var trueUserId = WebSecurity.CurrentUserId; 

     if (_authenticationSvc.GetUsersRoles(trueUserId).Any(x => x == "Admin")) return true; 
     // NullReferenceException on _authenticationSvc 
    } 
} 

Theo official docs tất cả những gì cần thiết là:

var builder = new ContainerBuilder(); 
builder.RegisterWebApiFilterProvider(GlobalConfiguration.Configuration); 

Nhưng điều đó dường như không làm thủ thuật. Đánh giá cao bất kỳ trợ giúp nào.

+1

Tôi nghĩ _authenticationSvc cần phải được một tài sản không phải là một lĩnh vực – MikeSW

+1

@MikeSW Bây giờ nó mang lại cho tôi ngoại lệ này: 'Không phạm vi với một Tag khớp 'AutofacWebRequest' có thể nhìn thấy từ phạm vi trong đó đã được yêu cầu. Điều này thường chỉ ra rằng một thành phần được đăng ký theo yêu cầu trên HTTP đang được yêu cầu bởi một thành phần SingleInstance() (hoặc một kịch bản tương tự.) Theo tích hợp web luôn yêu cầu các phụ thuộc từ DependencyResolver.Current hoặc ILifetimeScopeProvider.RequestLifetime, không bao giờ từ chính vùng chứa đó .' –

Trả lời

18

Bạn nên cấu hình tiêm bất động sản cho thuộc tính của bạn

public class MyAuthorizeAttribute : AuthorizeAttribute 
{ 
    public IAuthenticationSvc AuthenticationSvc { get; set; } 
} 

và xây dựng

builder.RegisterType<MyAuthorizeAttribute>().PropertiesAutowired(); 
9

Ngoài câu trả lời @Toan Nguyễn, nếu bạn có điều này ...

public class MyAuthorizeAttribute : AuthorizeAttribute 
{ 
    public IAuthenticationSvc AuthenticationSvc { get; set; } 
} 

... có vẻ như bạn cũng cần (hoặc có thể cần) dòng đầu tiên bên dưới:

builder.RegisterFilterProvider(); 
builder.RegisterType<MyAuthorizeAttribute>().PropertiesAutowired(); 

tham khảo: http://itprojectpool.blogspot.com.au/2014/03/autofac-di-on-action-filters.html

+1

Đúng, dòng đầu tiên đã sửa nó cho tôi. – Austin

+0

Vâng, đây là cho MVC phải không? Mã ví dụ trong câu hỏi là để đăng ký WebAPI. Mặc dù câu hỏi được gắn thẻ cho MVC, vì vậy, thông tin này là thích hợp, nó chỉ nên rõ ràng rằng phương pháp RegisterFilterProvider là MVC tương đương với 'RegisterWebApiFilterProvider' tôi nghĩ –

7

Tôi nghĩ rằng tài liệu Autofac của cung cấp giải pháp đơn giản hơn nhiều cho các bộ lọc hành động WebAPI.

public interface ServiceCallActionFilterAttribute : ActionFilterAttribute 
{ 
    public override void OnActionExecuting(HttpActionContext actionContext) 
    { 
    // Get the request lifetime scope so you can resolve services. 
    var requestScope = actionContext.Request.GetDependencyScope(); 

    // Resolve the service you want to use. 
    var service = requestScope.GetService(typeof(IMyService)) as IMyService; 

    // Do the rest of the work in the filter. 
    service.DoWork(); 
    } 
} 

Nó không phải là "DI nguyên chất" vì nó đang sử dụng định vị dịch vụ, nhưng nó đơn giản và hoạt động với phạm vi yêu cầu. Bạn không cần phải lo lắng về việc đăng ký bộ lọc hành động cụ thể cho mỗi bộ điều khiển WebApi.

Nguồn: http://autofac.readthedocs.io/en/latest/integration/webapi.html#provide-filters-via-dependency-injection

Các vấn đề liên quan