【问题标题】:Getting the User.Identity during service Resolution in Autofac and WebAPI 2 Owin在 Autofac 和 WebAPI 2 Owin 中的服务解析期间获取 User.Identity
【发布时间】:2015-04-13 17:30:44
【问题描述】:

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

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

下面的sn-p是从我的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&lt;Startup&gt;(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 实例。

【问题讨论】:

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


    【解决方案1】:

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

    我假设您的 IGlobalContext 有一个 User 方法,它接受一个用户名并返回一个用户,可能来自您的数据库,基于从当前上下文传入的用户名?

    您应该为您的网站和单元测试设置不同的 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();
    }
    

    我希望这会有所帮助?

    【讨论】:

    • 感谢您的意见。您在单元测试情况下是对的,我不需要访问 HttpContext,并且使用模拟用户的想法很有用,但我想我说错了。我不是真正的“单元”测试。我在这方面的测试背后的想法是确保我确实为每个用户创建了一个不同的 UserContext 实例,并且能够同时为多个用户进行测试。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-09
    • 1970-01-01
    • 2016-10-22
    • 1970-01-01
    • 2014-12-24
    相关资源
    最近更新 更多