尝试设置SignalR中心(规范聊天)以在OWIN托管的Nancy应用和MassTransit中运行。 MassTransit部分有效:
public ChatMessageConsumer(IEnumerable<IChatMessageProcessor> messageProcessors,
IChatHub chatHub,
ILogger logger) { ... }
public async Task Consume(ConsumeContext<IChatMessage> context)
{
_chatHub.BroadcastMessage( ... );
}
由MassTransit事件触发的消息到达我的浏览器客户端。从客户端触发的那些永远不会:
public class ChatHub : Hub, IChatHub
{
public ChatHub(ILifetimeScope lifetimeScope)
{
_hubLifetimeScope = lifetimeScope.BeginLifetimeScope();
// snip ...
}
// snip ...
}
public void Send(string name, string message)
{
// publish message on bus
_bus.Publish<IChatMessage>(/* snip ... */);
_hubInstanceContext.Clients.All.BroadcastMessage(/* ... */);
}
public void BroadcastMessage(string service, string message, string correlationId) { /* snip ... */ }
尽我所知,框架正在寻找一个无参数的构造函数,我没有(显然不需要)。在我的启动中,我创建了一个配置,将Autofac解析器注册为依赖项解析器,然后使用配置启动SignalR。 Nancy开始使用具有相同容器的Autofac bootstrapper。
public void Configuration(IAppBuilder app)
{
var container = ResolveDependencies();
var hubConfiguration = new HubConfiguration
{
EnableDetailedErrors = true,
Resolver = container.Resolve<IDependencyResolver>()
};
app.UseAutofacMiddleware(container);
app.MapSignalR(hubConfiguration);
app.Map("/site", sb => sb.UseNancy(options => options.Bootstrapper = new ChatBootstrapper(container)));
// snip MassTransit bus start/stop, etc. ...
}
static IContainer ResolveDependencies()
{
var builder = new ContainerBuilder();
// snip MassTransit consumers, etc. ...
builder.RegisterType<ChatHub>().As<IChatHub>().ExternallyOwned().SingleInstance();
builder.RegisterType<AutofacDependencyResolver>().As<IDependencyResolver>().SingleInstance();
builder.Register(i => i.Resolve<IDependencyResolver>()
.Resolve<IConnectionManager>()
.GetHubContext<ChatHub, IChatHub>())
.SingleInstance()
.ExternallyOwned();
// snip Logger registrations, etc. ...
}
Nancy正在工作(这就是我将事件发布到MassTransit的方式)。 MassTransit正在工作 - 事件被消耗并且能够广播客户端接收的SignalR事件。 SignalR部分工作 - 我显然已经连接到集线器,因为我可以接收来自MassTransit消费者的消息,但是当我尝试从客户端发送消息时,我收到500内部服务器错误。如果我向hub添加一个无参数构造函数,当我尝试从客户端发送时,会调用该构造函数,这让我认为我为SignalR设置Autofac的方式有问题。在这种情况下,当调用Send
方法时,应该通过构造函数中的DI设置的_hubInstanceContext
和_bus
成员为空。我已尝试添加IHubContext<IMyHub>
属性,如https://stackoverflow.com/a/36476106/173225中所述,但这种情况从未设置过,这使我怀疑在这种情况下根本没有使用DI。
我已经回顾了Autofac文档,这里有很多关于SO和一些博客文章的问题,但看不出我可能会遗漏的内容。我还应该注意,在将Autofac添加到混合中之前,我确实让客户端聊天工作(即我可以send
发送一条消息并收到broadcastMessage
。)
有什么建议吗?
编辑:在无参数构造函数中添加callstack:
> Chat.Service.exe!Chat.Service.Hubs.ChatHub.ChatHub() Line 25 C#
mscorlib.dll!System.Activator.CreateInstance(System.Type type, bool nonPublic) Unknown
mscorlib.dll!System.Activator.CreateInstance(System.Type type) Unknown
Microsoft.AspNet.SignalR.Core.dll!Microsoft.AspNet.SignalR.Hubs.DefaultHubActivator.Create(Microsoft.AspNet.SignalR.Hubs.HubDescriptor descriptor) Line 29 C#
Microsoft.AspNet.SignalR.Core.dll!Microsoft.AspNet.SignalR.Hubs.DefaultHubManager.ResolveHub(string hubName) Line 89 C#
Microsoft.AspNet.SignalR.Core.dll!Microsoft.AspNet.SignalR.Hubs.HubDispatcher.CreateHub(Microsoft.AspNet.SignalR.IRequest request, Microsoft.AspNet.SignalR.Hubs.HubDescriptor descriptor, string connectionId, Microsoft.AspNet.SignalR.Hubs.StateChangeTracker tracker, bool throwIfFailedToCreate) Line 455 C#
Microsoft.AspNet.SignalR.Core.dll!Microsoft.AspNet.SignalR.Hubs.HubDispatcher.OnReceived(Microsoft.AspNet.SignalR.IRequest request, string connectionId, string data) Line 180 C#
Microsoft.AspNet.SignalR.Core.dll!Microsoft.AspNet.SignalR.PersistentConnection.ProcessRequestPostGroupRead.AnonymousMethod__5() Line 282 C#
Microsoft.AspNet.SignalR.Core.dll!Microsoft.AspNet.SignalR.TaskAsyncHelper.FromMethod(System.Func<System.Threading.Tasks.Task> func) Line 771 C#
Microsoft.AspNet.SignalR.Core.dll!Microsoft.AspNet.SignalR.PersistentConnection.ProcessRequestPostGroupRead.AnonymousMethod__4(string data) Line 282 C#
Microsoft.AspNet.SignalR.Core.dll!Microsoft.AspNet.SignalR.Transports.ForeverTransport.ProcessSendRequest() Line 151 C#
[Resuming Async Method]
mscorlib.dll!System.Runtime.CompilerServices.AsyncMethodBuilderCore.MoveNextRunner.InvokeMoveNext(object stateMachine) Unknown
mscorlib.dll!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) Unknown
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) Unknown
mscorlib.dll!System.Runtime.CompilerServices.AsyncMethodBuilderCore.MoveNextRunner.Run() Unknown
Microsoft.AspNet.SignalR.Core.dll!Microsoft.AspNet.SignalR.TaskAsyncHelper.RunWithPreservedCulture.AnonymousMethod__72_0(System.Action f) Line 1036 C#
Microsoft.AspNet.SignalR.Core.dll!Microsoft.AspNet.SignalR.TaskAsyncHelper.RunWithPreservedCulture.AnonymousMethod__71_0(System.Action<System.__Canon> f, System.__Canon state) Line 1028 C#
Microsoft.AspNet.SignalR.Core.dll!Microsoft.AspNet.SignalR.TaskAsyncHelper.RunWithPreservedCulture<System.__Canon, System.__Canon, System.__Canon>(Microsoft.AspNet.SignalR.TaskAsyncHelper.CulturePair preservedCulture, System.Func<System.__Canon, System.__Canon, System.__Canon> func, System.__Canon arg1, System.__Canon arg2) Line 1009 C#
Microsoft.AspNet.SignalR.Core.dll!Microsoft.AspNet.SignalR.TaskAsyncHelper.RunWithPreservedCulture<System.Action>(Microsoft.AspNet.SignalR.TaskAsyncHelper.CulturePair preservedCulture, System.Action<System.Action> action, System.Action arg) Line 1031 C#
Microsoft.AspNet.SignalR.Core.dll!Microsoft.AspNet.SignalR.TaskAsyncHelper.RunWithPreservedCulture(Microsoft.AspNet.SignalR.TaskAsyncHelper.CulturePair preservedCulture, System.Action action) Line 1037 C#
Microsoft.AspNet.SignalR.Core.dll!Microsoft.AspNet.SignalR.TaskAwaiterHelper.PreserveCultureUnsafeOnCompleted.AnonymousMethod__0() Line 48 C#
mscorlib.dll!System.Threading.Tasks.AwaitTaskContinuation.RunOrScheduleAction(System.Action action, bool allowInlining, ref System.Threading.Tasks.Task currentTask) Unknown
mscorlib.dll!System.Threading.Tasks.Task.FinishContinuations() Unknown
mscorlib.dll!System.Threading.Tasks.Task.FinishStageThree() Unknown
mscorlib.dll!System.Threading.Tasks.Task<System.__Canon>.TrySetResult(System.__Canon result) Unknown
mscorlib.dll!System.Runtime.CompilerServices.AsyncTaskMethodBuilder<Microsoft.AspNet.SignalR.Hosting.INameValueCollection>.SetResult(Microsoft.AspNet.SignalR.Hosting.INameValueCollection result) Unknown
Microsoft.AspNet.SignalR.Core.dll!Microsoft.AspNet.SignalR.Owin.ServerRequest.ReadForm() Line 111 C#
[Resuming Async Method]
mscorlib.dll!System.Runtime.CompilerServices.AsyncMethodBuilderCore.MoveNextRunner.InvokeMoveNext(object stateMachine) Unknown
mscorlib.dll!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) Unknown
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) Unknown
mscorlib.dll!System.Runtime.CompilerServices.AsyncMethodBuilderCore.MoveNextRunner.Run() Unknown
Microsoft.AspNet.SignalR.Core.dll!Microsoft.AspNet.SignalR.TaskAsyncHelper.RunWithPreservedCulture.AnonymousMethod__72_0(System.Action f) Line 1036 C#
Microsoft.AspNet.SignalR.Core.dll!Microsoft.AspNet.SignalR.TaskAsyncHelper.RunWithPreservedCulture.AnonymousMethod__71_0(System.Action<System.__Canon> f, System.__Canon state) Line 1028 C#
Microsoft.AspNet.SignalR.Core.dll!Microsoft.AspNet.SignalR.TaskAsyncHelper.RunWithPreservedCulture<System.__Canon, System.__Canon, System.__Canon>(Microsoft.AspNet.SignalR.TaskAsyncHelper.CulturePair preservedCulture, System.Func<System.__Canon, System.__Canon, System.__Canon> func, System.__Canon arg1, System.__Canon arg2) Line 1009 C#
Microsoft.AspNet.SignalR.Core.dll!Microsoft.AspNet.SignalR.TaskAsyncHelper.RunWithPreservedCulture<System.Action>(Microsoft.AspNet.SignalR.TaskAsyncHelper.CulturePair preservedCulture, System.Action<System.Action> action, System.Action arg) Line 1031 C#
Microsoft.AspNet.SignalR.Core.dll!Microsoft.AspNet.SignalR.TaskAsyncHelper.RunWithPreservedCulture(Microsoft.AspNet.SignalR.TaskAsyncHelper.CulturePair preservedCulture, System.Action action) Line 1037 C#
Microsoft.AspNet.SignalR.Core.dll!Microsoft.AspNet.SignalR.TaskAwaiterHelper.PreserveCultureUnsafeOnCompleted.AnonymousMethod__0() Line 48 C#
mscorlib.dll!System.Threading.Tasks.AwaitTaskContinuation.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem() Unknown
mscorlib.dll!System.Threading.ThreadPoolWorkQueue.Dispatch() Unknown
mscorlib.dll!System.Threading._ThreadPoolWaitCallback.PerformWaitCallback() Unknown
[Async Call]
Microsoft.Owin.dll!Microsoft.Owin.Mapping.MapMiddleware.Invoke(System.Collections.Generic.IDictionary<string, object> environment) Line 64 C#
[Async Call]
Autofac.Integration.Owin.dll!Owin.AutofacAppBuilderExtensions.RegisterAutofacLifetimeScopeInjector.AnonymousMethod__0(Microsoft.Owin.IOwinContext context, System.Func<System.Threading.Tasks.Task> next) Line 333 C#
[Async Call]
Microsoft.Owin.Host.HttpListener.dll!Microsoft.Owin.Host.HttpListener.OwinHttpListener.ProcessRequestAsync(System.Net.HttpListenerContext context) Line 262 C#
[Async Call]
Microsoft.Owin.Host.HttpListener.dll!Microsoft.Owin.Host.HttpListener.OwinHttpListener.ProcessRequestsAsync() Line 244 C#
答案 0 :(得分:0)
我需要改变:
builder.RegisterType<ChatHub>().As<IChatHub>().ExternallyOwned().SingleInstance();
为:
builder.RegisterType<ChatHub>().ExternallyOwned();
builder.Register(c => c.Resolve<ChatHub>()).As<IChatHub>();
此时我并不完全确定原因,但我会在Autofac源代码中进行一些挖掘并更新此答案。
我之前尝试了很多变体,包含和不包含SingleInstance
和AsImplementedInterfaces
等等,但在我将其剥离回完全之前没有任何效果Autofac docs