获取Autofac和Web API 2 Owin中的服务解析期间的User.Identity

时间:2015-04-13 17:30:45

标签: c# asp.net-web-api2 autofac owin

我想要做的是实例化UserContext(理想情况下每个用户一个实例)。 UserContext取决于当前登录的用户。

MyUser是通过调用GlobalContext.User(username)

创建的

从我的Startup.Configuration(IAppBuilder app)

调用以下代码段
private static IContainer RegisterServices()
{
    var builder = new ContainerBuilder();
    builder.RegisterApiControllers(System.Reflection.Assembly.GetAssembly(typeof(MyWeb.API.Startup)));
    builder.RegisterType<GlobalContext>().As<IGlobalContext>().SingleInstance();
    builder.Register(c => c.Resolve<IGlobalContext>().User(
        HttpContext.Current.User.Identity.Name)
        ).As<MyUser>();
    builder.RegisterType<UserContext>().As<IUserContext>().InstancePerLifetimeScope();
    return builder.Build();
}

在IIS Express中运行时,一切似乎都能正常工作。 当我在使用Owin WebApp.Start<Startup>(url: BaseAddress) HttpContext.Current的集成测试中运行此操作时为空。这是我迄今为止所做的所有阅读的预期,但是替代方案是什么?

我想我需要访问owinContext或autofac生命周期范围才能在解析期间获取当前用户,但我该怎么做?

有更好的方法吗?或者我错过了一些微不足道的东西?

感谢所有帮助。

已编辑添加信息 如果它有帮助我在这里包括我的Configuration()方法:

using System.Web;
using System.Web.Http;
using Autofac;
using Autofac.Integration.WebApi;
using Owin;
using System.Reflection;

namespace SomeNameSpace
{

 public partial class Startup
    {

    public void Configuration(IAppBuilder app)
    {
        var configuration = new HttpConfiguration{ IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always };

        WebApiConfig.Register(configuration);
        BreezeConfig.Register(configuration);
        CorsConfig.Register(configuration);

        // Autofac IoC
        var container = RegisterServices();
        app.UseAutofacMiddleware(container);

        app.UseWindowsAuthentication();

        var urt = new UserRolesTranformer(new GlobalContext());
        app.UseClaimsTranformation(urt.Transformation);

        app.UseAutofacWebApi(configuration);
        configuration.DependencyResolver = new AutofacWebApiDependencyResolver(container);

        //app.Use(typeof(TestMiddleware));
        app.UseAutofacWebApi(configuration);
        app.UseWebApi(configuration);
    }
}

终极目标: 创建一个模拟多个并发用户登录的测试,并确保每个用户获得自己的UserContext实例。

1 个答案:

答案 0 :(得分:2)

在单元测试的情况下,您不应该真正需要访问HttpContext或OwinContext。正如我想象你已经发现的那样,单元测试没有HttpContext的概念。

我假设您的IGlobalContext有一个方法User,它接受一个Username并返回一个User,可能是根据当前上下文传入的Username从您的数据库返回的?

您应该为您的网站和单元测试进行不同的Autofac注册,以便您可以在每个环境中拥有不同的依赖关系。然后在单元测试Autofac注册中,您可以注册一个完全不同的依赖项,以便在单元测试中解析,或者您可以传入您的User方法,一个您知道存在的模拟用户名。

因此,您可以将此作为您网站上的Autofac注册。

private static IContainer RegisterServices()
{
    var builder = new ContainerBuilder();
    builder.RegisterApiControllers(System.Reflection.Assembly.GetAssembly(typeof(MyWeb.API.Startup)));
    builder.RegisterType<GlobalContext>().As<IGlobalContext>().SingleInstance();
    builder.Register(c => c.Resolve<IGlobalContext>().User(
        HttpContext.Current.User.Identity.Name)
        ).As<MyUser>();
    builder.RegisterType<UserContext>().As<IUserContext>().InstancePerLifetimeScope();
    return builder.Build();
}

然后在你的单元测试中,当你用这样的东西注册你的Autofac注册时。

private static IContainer RegisterServices()
{
    var builder = new ContainerBuilder();
    builder.RegisterApiControllers(System.Reflection.Assembly.GetAssembly(typeof(MyWeb.API.Startup)));
    builder.RegisterType<GlobalContext>().As<IGlobalContext>().SingleInstance();
    builder.Register(c => c.Resolve<IGlobalContext>().User(
        "MyTestUser")
        ).As<MyUser>();
    builder.RegisterType<UserContext>().As<IUserContext>().InstancePerLifetimeScope();
    return builder.Build();
}

通过这种方式,您可以在单元测试中了解您传入的用户以及应该返回的用户。

或者使用像你这样完全嘲笑的用户......

public class TestUser : MyUser
{
    //Known Test Scenario Properties and Methods as required
}

private static IContainer RegisterServices()
{
    var builder = new ContainerBuilder();
    builder.RegisterApiControllers(System.Reflection.Assembly.GetAssembly(typeof(MyWeb.API.Startup)));
    builder.RegisterType<GlobalContext>().As<IGlobalContext>().SingleInstance();
    builder.RegisterType<TestUser>().As<MyUser>();
    builder.RegisterType<UserContext>().As<IUserContext>().InstancePerLifetimeScope();
    return builder.Build();
}

我希望这有帮助吗?