1

我想配置一个MVC 5应用程序以使用SignalR 2.2.x并将服务注入到我的NotificationsHub中。 我们使用Autofac for MVC,但我不确定如何正确配置它。 Autofac文档存在NuGet Autofac.Integration.SignalR(3.0.2)和Autofac.Integration.Mvc(3.3.4)。如何在MVC 5应用程序中配置Autofac和SignalR

我在做什么,到目前为止是通过注册中心:

ContainerBuilder builder = new ContainerBuilder(); 

// Register MVC controllers. 
builder.RegisterControllers(typeof(MvcApplication).Assembly); 

builder.RegisterType<ServiceForSignalRHub>().AsImplementedInterfaces(); 
builder.RegisterType<...>().AsImplementedInterfaces(); 

builder.RegisterHubs(Assembly.GetExecutingAssembly()); 


IContainer container = builder.Build(); 


DependencyResolver.SetResolver(new AutofacDependencyResolver(container)); 

但是调用.SetResolver(...)是ambigious,因为它在这两个MVC和SignalR集成软件包存在。怎么办?我无法确认我的服务的构造器注入是否适用于我正在使用的Hub。

编辑

我可以Autofac就好配置MVC5。我迷失的地方是如何使用Autofac Signal集成NuGet来处理SignalR。 请参阅下面。

这是我的启动类:

public partial class Startup 
{ 
    public void Configuration(IAppBuilder app) 
    { 
     var defaultFactory = LogManager.Use<DefaultFactory>(); 
     defaultFactory.Directory("@D:\\NServiceBus\\"); 
     defaultFactory.Level(LogLevel.Debug); 

     var container = ConfigureAutofac(app); 

     ConfigureServiceBus(container, app); 

     app.UseAutofacMiddleware(container); // REGISTER WITH OWIN 
     app.UseAutofacMvc(); 

     ConfigureAuth(app); 

     GlobalConfiguration.Configuration.UseSqlServerStorage("hangfire"); 

     ConfigureSignalR(app); 
    } 
} 

这是我配置SignalR部分:

public partial class Startup 
{ 
    public void ConfigureSignalR(IAppBuilder app) 
    { 
     var builder = new ContainerBuilder(); 

     builder.RegisterHubs(Assembly.GetExecutingAssembly()).PropertiesAutowired(); 
     builder.RegisterType<MaintenanceService>().As<IMaintenanceService>().PropertiesAutowired(); 

     var container = builder.Build(); 
     //var container = new AutofacContainer().Container; 

     var resolver = new AutofacDependencyResolver(container); 

     // Any connection or hub wire up and configuration should go here 
     app.MapSignalR(new HubConfiguration 
     { 
      Resolver = resolver, 
      EnableJSONP = true, 
      EnableDetailedErrors = true, 
      EnableJavaScriptProxies = true 
     }); 

     builder.RegisterInstance(resolver.Resolve<IConnectionManager>()); 
    } 
} 

怎么可以这样做正确?

回答

2

当您映射SignalR时,您应该明确告诉SignalR使用AutofacDependencyResolver。 我假设你知道在你的Startup类,你必须调用app.MapSignalR();

当你映射它,你应该告诉它使用自定义依赖解析器(在AutofacDependencyResolver)。

这里是我如何做到这一点:

var resolver = new AutofacDependencyResolver(container); 

     app.MapSignalR(new HubConfiguration 
     { 
      Resolver = resolver 
     }); 

这样一来,你告诉SignalR直接其中依赖解析器使用。

我有一个GitHub repo for SignalR Dependency Injection,但它没有配置为使用MVC。不过,我认为它会给你提示如何创建你的配置。

注意:如果您使用的是OWIN中间件,请确保不要使用AT ALL的GlobalHost静态属性,因为它会有很大的不一致性。

A common error in OWIN integration is use of the GlobalHost. In OWIN you create the configuration from scratch. You should not reference GlobalHost anywhere when using the OWIN integration.

再次,检查我给你的回购看看如何做到这一点。

希望这会有所帮助:) 祝你好运!

+0

感谢您的好回答。我没有得到它在我的最终工作。由于我使用MVC5,我的项目设置稍有不同。我确实使用OWIN。有一件事:我抓住你的回购,并做了一个软件包更新,以匹配我使用的版本号。现在演示不会运行。 – John

+0

是的,这是因为使用Redis的SignalR背板。从中删除所有与Redis相关的事物。我会尽快提交更改,但在此之前,请删除关于Redis的所有内容:启动时的app.UseRedis和Microsoft.AspNet.SignalR.Redis NuGet包。它会工作:)询问是否有任何问题,我会尽力更新它:)祝你好运! –

+0

谢谢你做到了。我仍然不确定如何配置MVC Autofac和SignalR Autofac,但接下来的问题是我得到了一个SignalR JS错误:“SignalR:Connection尚未完全初始化,请使用.start()。done()或.start ().fail()在连接启动后运行逻辑。“有什么建议?再次感谢! – John

0

我结束了这个(注意注释):

public partial class Startup 
{ 
    public void Configuration(IAppBuilder app) 
    { 
     ConfigureAuth(app); 

     IContainer container = AutofacConfig(app); 
     app.UseAutofacMiddleware(container); 
     app.UseAutofacMvc(); 
     DependencyResolver.SetResolver(new Autofac.Integration.Mvc.AutofacDependencyResolver(container)); 
     GlobalConfiguration.Configuration.DependencyResolver = new AutofacWebApiDependencyResolver(container); 
     app.UseAutofacWebApi(GlobalConfiguration.Configuration); 

     var hubConfiguration = new Microsoft.AspNet.SignalR.HubConfiguration() 
     { 
      // Resolve presolver from container 
      Resolver = container.Resolve<Microsoft.AspNet.SignalR.IDependencyResolver>(), 
     }; 
     app.MapSignalR(hubConfiguration); 

     AreaRegistration.RegisterAllAreas(); 
     GlobalConfiguration.Configure(WebApiConfig.Register); 

     FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); 
     RouteConfig.RegisterRoutes(RouteTable.Routes); 
     BundleConfig.RegisterBundles(BundleTable.Bundles); 
    } 

_

private static IContainer AutofacConfig(IAppBuilder app) 
    { 
     var builder = new ContainerBuilder(); 

     RegisterSignalR(builder); 

     return builder.Build(); 
    } 

_

private static void RegisterSignalR(ContainerBuilder builder) 
    { 
     // Register Autofac resolver into container to be set into HubConfiguration later 
     builder.RegisterType<Autofac.Integration.SignalR.AutofacDependencyResolver>() 
       .As<Microsoft.AspNet.SignalR.IDependencyResolver>() 
       .SingleInstance(); 

     // Register ConnectionManager as IConnectionManager so that you can get 
     // hub context via IConnectionManager injected to your service 
     builder.RegisterType<Microsoft.AspNet.SignalR.Infrastructure.ConnectionManager>() 
       .As<Microsoft.AspNet.SignalR.Infrastructure.IConnectionManager>() 
       .SingleInstance(); 

     // Register hubs one by one 
     builder.RegisterType<MessageNotificationsHub>().ExternallyOwned(); 
     builder.RegisterType<SystemNotificationsHub>().ExternallyOwned(); 
    } 

感谢@Nathan和his answer(最初发现here)并想出将ConnectionManager注册为ICon的逻辑思维nectionManager

相关问题