I decided to clean this post up and I posted a sample project at ge.tt/3EwoZEd/v/0?c
Spent around 30 hours on this already and still can't figure it out... help would be really appreciated!
I have an ASP.NET Web API solution that uses this code: http://www.piotrwalat.net/basic-http-authentication-in-asp-net-web-api-using-message-handlers/ to implement "Basic HTTP authentication in ASP.NET Web API using Message Handlers". I'm new to IoC/DI and I'm trying to get this to work with Castle Windsor.
I've been trying a lot of different things but I get 1 of the following errors depending on what I did wrong:
- "Looks like you forgot to register the http module Castle.MicroKernel.Lifestyle.PerWebRequestLifestyleModule"
- "Object reference not set to an instance of an object." for the PrincipalProvider in BasicAuthMessageHandler
- "No component for supporting the service *.DummyPrincipalProvider was found"
Below is my code:
Global.asax.cs:
private static IWindsorContainer _container;
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
var config = (CustomErrorsSection)ConfigurationManager.GetSection("system.web/customErrors");
IncludeErrorDetailPolicy errorDetailPolicy;
switch (config.Mode)
{
case CustomErrorsMode.RemoteOnly:
errorDetailPolicy
= IncludeErrorDetailPolicy.LocalOnly;
break;
case CustomErrorsMode.On:
errorDetailPolicy
= IncludeErrorDetailPolicy.Never;
break;
case CustomErrorsMode.Off:
errorDetailPolicy
= IncludeErrorDetailPolicy.Always;
break;
default:
throw new ArgumentOutOfRangeException();
}
GlobalConfiguration.Configuration.IncludeErrorDetailPolicy = errorDetailPolicy;
ConfigureWindsor(GlobalConfiguration.Configuration);
GlobalConfiguration.Configuration.MessageHandlers.Add(new BasicAuthMessageHandler()
{
PrincipalProvider = _container.Resolve<IProvidePrincipal>()
});
}
public static void ConfigureWindsor(HttpConfiguration configuration)
{
// Create / Initialize the container
_container = new WindsorContainer();
// Find our IWindsorInstallers from this Assembly and optionally from our DI assembly which is in abother project.
_container.Install(FromAssembly.This());
_container.Kernel.Resolver.AddSubResolver(new CollectionResolver(_container.Kernel, true));
//Documentation http://docs.castleproject.org/Windsor.Typed-Factory-Facility.ashx
// Set the WebAPI DependencyResolver to our new WindsorDependencyResolver
var dependencyResolver = new WindsorDependencyResolver(_container);
configuration.DependencyResolver = dependencyResolver;
}
Windsor Installer:
public class PrincipalsInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(Classes.FromThisAssembly().BasedOn<DelegatingHandler>());
container.Register(
Component.For<IProvidePrincipal>().ImplementedBy<DummyPrincipalProvider>()
);
}
}
Modified DummyPrincipalProvider (from the original I got from the URL above):
public class DummyPrincipalProvider : IProvidePrincipal
{
private IUserRepository _userRepo;
public DummyPrincipalProvider(IUserRepository userRepo)
{
this._userRepo = userRepo;
}
public IPrincipal CreatePrincipal(string username, string password)
{
try
{
if (!this._userRepo.ValidateUser(username, password))
{
return null;
}
else
{
var identity = new GenericIdentity(username);
IPrincipal principal = new GenericPrincipal(identity, new[] { "User" });
if (!identity.IsAuthenticated)
{
throw new ApplicationException("Unauthorized");
}
return principal;
}
}
catch
{
return null;
}
}
}
WindsorDependencyResolver.cs:
internal sealed class WindsorDependencyResolver : IDependencyResolver
{
private readonly IWindsorContainer _container;
public WindsorDependencyResolver(IWindsorContainer container)
{
if (container == null)
{
throw new ArgumentNullException("container");
}
_container = container;
}
public object GetService(Type t)
{
return _container.Kernel.HasComponent(t) ? _container.Resolve(t) : null;
}
public IEnumerable<object> GetServices(Type t)
{
return _container.ResolveAll(t).Cast<object>().ToArray();
}
public IDependencyScope BeginScope()
{
return new WindsorDependencyScope(_container);
}
public void Dispose()
{
}
}
WindsorDependencyScope.cs:
internal sealed class WindsorDependencyScope : IDependencyScope
{
private readonly IWindsorContainer _container;
private readonly IDisposable _scope;
public WindsorDependencyScope(IWindsorContainer container)
{
if (container == null)
{
throw new ArgumentNullException("container");
}
_container = container;
_scope = container.BeginScope();
}
public object GetService(Type t)
{
return _container.Kernel.HasComponent(t) ? _container.Resolve(t) : null;
}
public IEnumerable<object> GetServices(Type t)
{
return _container.ResolveAll(t).Cast<object>().ToArray();
}
public void Dispose()
{
_scope.Dispose();
}
}