使用Autofac解决MVC5应用程序中的IOwinContext

时间:2014-02-11 13:30:32

标签: asp.net-mvc asp.net-mvc-5 autofac owin membershipreboot

我在使用MembershipReboot新ASP MVC5模板和Autofac时遇到问题。我使用默认的MVC5模板来设置站点,然后尝试连接MembershipReboot框架,作为模板附带的ASP Identity框架的替代。

我遇到的这个问题是尝试从IOwinContext容器解析Autofac。这是我在Startup课程中的布线(切入基础知识)。这是MembershipReboot Owin应用程序样本中使用的布线(除非他使用Nancy)。

public partial class Startup
 {
    public void Configuration(IAppBuilder app)
    {
        var builder = new ContainerBuilder();
        builder.RegisterControllers(Assembly.GetExecutingAssembly());

        builder.Register(c => new DefaultUserAccountRepository())
            .As<IUserAccountRepository>()
            .As<IUserAccountQuery>()
            .InstancePerLifetimeScope();

        builder.RegisterType<UserAccountService>()
            .AsSelf()
            .InstancePerLifetimeScope();

        builder.Register(ctx =>
        {
            **var owin = ctx.Resolve<IOwinContext>();** //fails here
            return new OwinAuthenticationService(
                MembershipRebootOwinConstants.AuthenticationType,
                ctx.Resolve<UserAccountService>(),
                owin.Environment);
        })
            .As<AuthenticationService>()
            .InstancePerLifetimeScope();

        var container = builder.Build();
        DependencyResolver.SetResolver(new AutofacDependencyResolver(container));

        ConfigureAuth(app);
        app.Use(async (ctx, next) =>
        {
            using (var scope = container.BeginLifetimeScope(b =>
            {
                b.RegisterInstance(ctx).As<IOwinContext>();
            }))
            {
                ctx.Environment.SetUserAccountService(() => scope.Resolve<UserAccountService>());
                ctx.Environment.SetAuthenticationService(() => scope.Resolve<AuthenticationService>());
                await next();
            }
        });
    }

这是我的控制器,它具有在控制器构造函数中指定的依赖关系。

public class HomeController : Controller
{
    private readonly AuthenticationService service;

    public HomeController(AuthenticationService service)
    {
        this.service = service;
    }

    public ActionResult Index()
    {
        return View();
    }

    public ActionResult About()
    {
        ViewBag.Message = "Your application description page.";

        return View();
    }

    public ActionResult Contact()
    {
        ViewBag.Message = "Your contact page.";

        return View();
    }
}

似乎我需要将Autofac容器包装在AutofacDependencyResolver中,以便MVC框架使用容器来解析组件。这是Nancy Owin示例和我在MVC5中使用的唯一主要区别。

当我这样做时,它似乎(来自我的跟踪)好像在没有先通过OWIN middleware堆栈的情况下解析依赖关系,因此IOwinContext永远不会被注册。

我在这里做错了什么?

更新

Brock,当我将配置迁移到我的项目时,您的新示例工作正常。仅仅为了我的理解,似乎你的新样本中的这一行用容器注册了当前的OwinContext,这是以前缺少的。

builder.Register(ctx=>HttpContext.Current.GetOwinContext()).As<IOwinContext>();

那是

1 个答案:

答案 0 :(得分:5)

有一个较新的样本使用AutoFac for MVC进行DI:

https://github.com/brockallen/BrockAllen.MembershipReboot/blob/master/samples/SingleTenantOwinSystemWeb/SingleTenantOwinSystemWeb/Startup.cs

看看这是否有帮助。

如果您不想使用HttpContext.Current,可以执行以下操作:

app.Use(async (ctx, next) =>
{
    // this creates a per-request, disposable scope
    using (var scope = container.BeginLifetimeScope(b =>
    {
        // this makes owin context resolvable in the scope
        b.RegisterInstance(ctx).As<IOwinContext>();
    }))
    {
        // this makes scope available for downstream frameworks
        ctx.Set<ILifetimeScope>("idsrv:AutofacScope", scope);
        await next();
    }
}); 

这就是我们在内部为我们的某些应用做的事情。您需要连接Web API服务解析器以查找“idsrv:AutofacScope”。 Tugberk有一个帖子:

http://www.tugberkugurlu.com/archive/owin-dependencies--an-ioc-container-adapter-into-owin-pipeline