12

Próbuję rozwiązać zależności mojego niestandardowego AuthorizeAttribute, którego używam do ozdabiania kontrolerów API w aplikacji MVC4. Problem polega na tym, że wciąż uzyskuję NullReferenceException zależność usługi, której używam w moim filtrze niestandardowym. Oto moja konfiguracja Autofac:Wstrzykiwanie zależności do niestandardowego atrybutu filtru działania Web API z 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; 
    } 
} 

i mój zwyczaj zezwolić filtr:

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 
    } 
} 

Według official docs wszystko, co potrzebne jest:

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

Ale to nie wydaje się rób to. Doceniam każdą pomoc.

+1

myślę _authenticationSvc musi być nie własność pole – MikeSW

+1

@MikeSW Teraz to daje mi ten wyjątek: 'no z zakresu dopasowania tag„AutofacWebRequest”jest widoczny od zakresu, w którym wystąpiono o wystąpienie instancji. Zasadniczo oznacza to, że komponent zarejestrowany jako żądanie na HTTP jest żądany przez komponent SingleInstance() (lub podobny scenariusz). W ramach integracji sieciowej zawsze żądaj zależności od DependencyResolver.Current lub ILifetimeScopeProvider.RequestLifetime, nigdy z samego kontenera . " –

Odpowiedz

18

Należy skonfigurować zastrzyk nieruchomości dla atrybutu

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

i budowniczego

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

Oprócz odpowiedzi @Toan Nguyen, jeśli masz ten ...

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

... wydaje się, że potrzebujesz (lub możesz potrzebować) pierwszej linii poniżej:

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

referencyjny: http://itprojectpool.blogspot.com.au/2014/03/autofac-di-on-action-filters.html

+1

Tak, ta pierwsza linia naprawiła to dla mnie. – Austin

+0

Cóż, to jest dla MVC, prawda? Przykładowy kod w pytaniu dotyczy rejestracji WebAPI. Chociaż pytanie jest również oznaczane dla MVC, więc ta informacja jest istotna, powinno być jasne, że metoda RegisterFilterProvider jest odpowiednikiem MVC 'RegisterWebApiFilterProvider' –

7

myślę dokumentacja Autofac oferuje znacznie prostsze rozwiązanie dla filtrów działania 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(); 
    } 
} 

Nie jest "czystym DI", ponieważ korzysta z lokalizatora usług, ale jest prosty i działa z zakresem żądania. Nie musisz martwić się o rejestrowanie konkretnego filtra akcji dla każdego kontrolera WebApi.

Źródło: http://autofac.readthedocs.io/en/latest/integration/webapi.html#provide-filters-via-dependency-injection