如何在身份验证中为AccountController配置Unity容器

时间:2017-08-05 18:42:35

标签: c# asp.net-web-api2 asp.net-identity unity-container

我的控制器就像:

public class AccountController : ApiController
{
    private const string LocalLoginProvider = "Local";
    private ApplicationUserManager _userManager;
    private readonly ApplicationRoleManager _roleManager;

    public AccountController()
    {
    }

    public AccountController(ApplicationUserManager userManager,
        ISecureDataFormat<AuthenticationTicket> accessTokenFormat,
        ApplicationRoleManager roleManager)
    {
        UserManager = userManager;
        AccessTokenFormat = accessTokenFormat;
        _roleManager = roleManager;

    }
}

在UnityConfig.cs中,我尝试这样配置:

    public static void RegisterTypes(IUnityContainer container)
    {
        // NOTE: To load from web.config uncomment the line below. Make sure to add a Microsoft.Practices.Unity.Configuration to the using statements.
        // container.LoadConfiguration();

        // TODO: Register your types here
        container.RegisterType<AccountController>(new InjectionConstructor());
        container.RegisterType<ApplicationUserManager>();
        container.RegisterType<ApplicationRoleManager>();
        container.RegisterType<ISecureDataFormat<AuthenticationTicket>, SecureDataFormat<AuthenticationTicket>>();
    }

在WebApiConfig.cs中:

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        var container = new UnityContainer();
        UnityConfig.RegisterTypes(container);
        //Set the unity container as the default dependency resolver
        config.DependencyResolver = new UnityHierarchicalDependencyResolver(container);
    }
}

在Global.asax.cs中:

public class WebApiApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        GlobalConfiguration.Configure(WebApiConfig.Register); // At the beginning, register with HttpConfiguration
        AreaRegistration.RegisterAllAreas();
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);
    }
}

但是当我尝试使用roleManager(var role = await _roleManager.FindByIdAsync(model.RoleId);)检索角色时,它说:

  

对象引用未设置为对象的实例。

我看到有一个类似的问题here,但它无法解决我的问题。

1 个答案:

答案 0 :(得分:1)

根据问题代码的外观,我相信您正在使用.NET Web API的Unity引导程序,它应该连接UnityDependencyResolver

container.RegisterType<AccountController>(new InjectionConstructor());

这会注册AccountController并指示Unity使用无参数构造函数。这就是为什么所有依赖项都为null。如果要使用其他构造函数,请删除AccountController注册,Unity将使用具有最多参数的构造函数。但是,如果执行此操作,则会在尝试解析AccountController时遇到运行时错误,因为ISecureDataFormat<>未注册,Unity将不知道如何将该接口映射到具体类型。

如果您将映射注册到SecureDataFormat<>,那么还需要注册一些其他依赖项。

container.RegisterType(typeof(ISecureDataFormat<>), typeof(SecureDataFormat<>));
container.RegisterType<ITextEncoder, Base64UrlTextEncoder>()
container.RegisterType<IDataSerializer<AuthenticationTicket>, TicketSerializer>()        
container.RegisterType<IDataProtector>(new ContainerControlledLifetimeManager(),
    new InjectionFactory(c => new DpapiDataProtectionProvider().Create("App Name")));

请注意,上述注册未经过测试。不确定是否应该为OWIN配置数据保护(并且可能从OWIN配置中获取保护提供程序)。

以下两个注册并不是严格要求的,因为Unity知道如何在没有注册的情况下解析具体类型,并且不提供额外的InjectionMembers(例如,生命周期,参数覆盖等)。

container.RegisterType<ApplicationUserManager>();
container.RegisterType<ApplicationRoleManager>();