Autofac & AuthenticationService

Hi,

I am using AutoFac instead of Funq and using a custom CredentialsAuthProvider in a MVC 5 project.

When I try to resolve AuthenticationService I am getting null back.

My impression was that AuthenticationService was was registered as part of the plugin setup, in my case:

          ////Register Autofac IoC container adapter, so ServiceStack can use it
          var adapter = new AutofacIocAdapter(_autofacContainer);
          container.Adapter = adapter;

          ....

          Plugins.Add(new AuthFeature(() => new AuthUserSession(),
              new IAuthProvider[] {
                  new CustomCredentialsAuthProvider(userService)
          }));

This doesn’t seem to be the case. I’ve had both a Custom Auth Provider working before and used Autofac before with ServiceStack successfully.

The Services are pre-registered and autowired in Funq although when you use an Adapter it takes over resolving the dependencies first, will only fallback when it can’t find the dep in the Adapter.

What does your impl of AutofacIocAdapter look like? and please provide the code you’re using to resolve AuthenticationService and where you’re trying to resolve it? i.e. in AppHost or at runtime?

AutofacIocAdapter is straight off GitHub

public class AutofacIocAdapter : IContainerAdapter
{
    private readonly IContainer _container;

    public AutofacIocAdapter(IContainer container)
    {
        _container = container;
    }

    public T Resolve<T>()
    {
        return _container.Resolve<T>();
    }

    public T TryResolve<T>()
    {
        T result;

        if (_container.TryResolve<T>(out result))
        {
            return result;
        }

        return default(T);
    }
}

I was just using constructor injection in a controller…

    private AuthenticateService _authenticationService;
    private IUserService _userService;

    public AccountController(AuthenticateService authenticationService, IUserService userService)
    {
        _authenitcationService = authenticationService;//ServiceStack Authentication
        _userService = userService;
    }

   AuthenticateResponse response = _authenticationService.Authenticate(new Authenticate
   {
           UserName = model.Username,
           Password = model.Password,
           RememberMe = model.RememberMe
    });//Authenticate against ServiceStack as well.

I’ve tried to resolve it in the AppHost as well. I can resolve the ICacheClient instance I’ve explicitly registered just fine.

        var foo = TryResolve<AuthenticateService>(); //null
        var bar = _autofacContainer.ResolveOptional<AuthenticateService>();//null
        var cache = Resolve<ICacheClient>();//fine

Ok so the Services that are added in Plugins, e.g. AuthenticateService are dynamically added when the plugin is loaded which happens after Configure() is called, so you’ll only be able to resolve it after the plugins are loaded which you can do by overriding OnAfterInit() in your AppHost, e.g:

public override void OnAfterInit()
{
    base.OnAfterInit();

    using (var authService = Container.Resolve<AuthenticateService>()) {
    }
}

But Services differ from Dependencies in that they also need to be injected with the current Request Context which can only happen during the context of a HTTP Request, this is needed for any Service that accesses base.Request which AuthenticateService does in a few places so you can’t call it on AppStart unless you inject it with a Mock Request, here’s an example of injecting a Mock Request to execute a Service that uses base.Request on AppStartup.

However AuthenticateService is going to be difficult to Mock and you wont be able to authenticate with OAuth/OpenId or anything else that relies on being executed from a browser with redirects. I’m not sure what you want to do with Auth Service on Startup but I recommend that you instead access the dependencies directly (e.g. IAuthRepository) at Startup. Also for an example of MVC + SS Auth see the HomeController in mvc.servicestack.net demo.

The recommended/supported API to resolve a Service is to use therefore ResolveService<T> API’s which both resolves it from the IOC + injects the current Request context. You can access this from either in your MVC Controller that inherits from ServiceStackController:

using (var authService = base.ResolveService<T>()) { ... }

Or if preferred you can just execute a Request DTO without resolving the Service with:

var response = base.Execute(new Authenticate { ... });

If outside of ServiceStack or MVC Controller (but still in the context of a Request) you can use the singleton:

HostContext.ResolveService<T>(IRequest)
HostContext.ServiceController.Execute(requestDto)

Thanks for your time, that’s sorted.