Trying to set up a SignalR hub (the canonical chat) to run in an OWIN-hosted Nancy app and MassTransit. The MassTransit part works:
public ChatMessageConsumer(IEnumerable<IChatMessageProcessor> messageProcessors,
IChatHub chatHub,
ILogger logger) { ... }
public async Task Consume(ConsumeContext<IChatMessage> context)
{
_chatHub.BroadcastMessage( ... );
}
Those messages triggered by MassTransit events get to my browser client. The ones triggered from the client never do:
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 ... */ }
As best as I can tell, the framework is looking for a parameterless constructor, which I don't have (and obviously don't want). In my startup I create a configuration, register the Autofac resolver as the dependency resolver, and start SignalR with the configuration. Nancy is started using an Autofac bootstrapper with the same container.
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 is working (that's how I post events to MassTransit). MassTransit is working -- events are consumed and are able to broadcast SignalR events that are received by the client. SignalR is partially working -- I've obviously got a connection to a hub because I can receive messages broadcast from MassTransit consumers, but when I try to send a message from a client, I get a 500 internal server error. If I add a parameterless constructor to the hub, when I try to send from the client, that constructor is called, leading me to think that there's something wrong with how I've setup Autofac for SignalR. In that case, when the Send
method is called, the _hubInstanceContext
and _bus
members, that should have been set via DI in the constructor are null. I've tried adding a IHubContext<IMyHub>
property, as suggested in https://stackoverflow.com/a/36476106/173225, but that is never set, supporting my suspicion that DI isn't being used at all in this case.
I've reviewed the Autofac docs, many questions here on SO and several blog posts, but can't see what I might be missing. I should also note I did have the client chat working before adding Autofac to the mix (i.e. I could send
a message and receive a broadcastMessage
).
Any suggestions?
Edit: adding callstack in parameterless constructor:
> 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#
Install-Package Autofac.SignalR
and then following docs.autofac.org/en/latest/integration/…? AFAIK I have followed the instructions in the docs. That's why I included my startupConfiguration
code, in case I missed something. – Colin Youngconfig.Resolver
is the correct one (ieAutofacDependencyResolver
) ? – Cyril DurandhubConfiguration.Resolver.GetType()
yields{Name = "AutofacDependencyResolver" FullName = "Autofac.Integration.SignalR.AutofacDependencyResolver"}
– Colin Young