I am working on an ASP.Net MVC project that authenticates using ADFS and uses SimpleInjector as the IoC container. The service layer of the application is in a different project and services are injected in the controller constructors on startup. One of these services is a user service which I would like to use to get user info etc. from my data layer.
I have a custom Principal (inherited from the ClaimsPrincipal) that I would like to use this user service on and store user information in. The issue I face is I'm not sure how to "glue" the user service to the custom principal.
I've tried getting an instance of the user service after each authentication and injecting it into the identity but I get an error saying the container doesn't contain and instance of the service. My code is below:
Application_Start()
protected void Application_Start()
{
// Register the IoC container
InjectorConfig.RegisterDependencies(_container);
// RouteConfig etc...
}
InjectorConfig
public class InjectorConfig
{
/// <summary>
/// Create the IoC container and register all dependencies
/// </summary>
public static void RegisterDependencies(Container container)
{
// Create the IoC container
//var container = new Container();
// Get the assembly that houses the services
var serviceAssembly = typeof (UserService).Assembly;
// Interate through the assembly and find all the services
var registrations = (
from type in serviceAssembly.GetExportedTypes()
where type.Namespace == "MyApp.Services"
where type.GetInterfaces().Any()
select new
{
Service = type.GetInterfaces().Single(),
Implementation = type,
});
// Register each of the services
foreach (var registration in registrations)
{
container.Register(registration.Service, registration.Implementation, Lifestyle.Transient);
}
// Verify the container and set the MVC dependency resolver
container.Verify();
DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container));
}
}
My Custom ClaimsPrincipal
public class MyCustomPrincipal : ClaimsPrincipal
{
private readonly IUserService _userService;
public MyCustomPrincipal(IIdentity identity, IUserService userService)
:base(identity)
{
this._userService = userService;
}
public override bool IsInRole(string role)
{
return this._userService.IsInRole(this.Identity.GetUserId(), role);
}
}
My User Service (In different assembly)
public class UserService : IUserService
{
public bool IsInRole(string currentUserId, string roleName)
{
// Check roles here
return true;
}
}
Application_PostAuthenticateRequest()
This is where the error occurs. No instance available
protected void Application_PostAuthenticateRequest()
{
var currentUser = ClaimsPrincipal.Current.Identity;
// This is where the error occurs. No instance available
var userService = this._container.GetInstance<IUserService>();
HttpContext.Current.User = new MyCustomPrincipal(currentUser, userService);
}
I'm a bit of an IoC rookie, so there's probably a simple solution to it but I'm bashing my head against a wall (figuratively speaking) trying to work this one out.
Any help you could provide would be greatly appreciated!
Updated Here is the exception detail
SimpleInjector.ActivationException was unhandled by user code
HResult=-2146233088
Message=No registration for type IUserService could be found.
Source=SimpleInjector
StackTrace:
at SimpleInjector.Container.ThrowMissingInstanceProducerException(Type serviceType)
at SimpleInjector.Container.GetInstanceFromProducer(InstanceProducer instanceProducer, Type serviceType)
at SimpleInjector.Container.GetInstanceForType[TService]()
at SimpleInjector.Container.GetInstance[TService]()
at MyWebApp.Web.MvcApplication.Application_PostAuthenticateRequest() in c:\Projects\MyWebApp\Client\\MyWebApp.Web\Global.asax.cs:line 46
InnerException: