I have 2 systems, one for publish messages and other for consume them. Both are using Masstransit (with RabbitMQ) and are implemented using ASP.Net web api 2 and OWIN (and Autofac as IoC container). Everything works fine if my consumer has no dependencies, but when I inject a dependenciy into my consumer, the Consume method is never executed (no error is throwing during initialization).
This is the relevant Publisher code:
//Startup.cs
public class Startup
{
public void Configuration(IAppBuilder app)
{
HttpConfiguration config = new HttpConfiguration();
IContainer container = null;
var builder = new ContainerBuilder();
builder.Register(context =>
{
var busControl = Bus.Factory.CreateUsingRabbitMq(cfg =>
{
IRabbitMqHost rabbitMqHost = cfg.Host(new Uri(ConfigurationManager.AppSettings["RabbitMQHost"]), settings =>
{
settings.Username(ConfigurationManager.AppSettings["RabbitMQUser"]);
settings.Password(ConfigurationManager.AppSettings["RabbitMQPassword"]);
});
});
return busControl;
})
.As<IBusControl>()
.As<IBus>()
.SingleInstance();
// Register Web API controllers
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
// Resolve dependencies
container = builder.Build();
config.DependencyResolver = AutofacWebApiDependencyResolver(container);
WebApiConfig.Register(config);
SwaggerConfig.Register(config);
app.UseCors(CorsOptions.AllowAll);
// Register the Autofac middleware FIRST.
app.UseAutofacMiddleware(container);
app.UseWebApi(config);
// Starts MassTransit Service bus, and registers stopping of bus on app dispose
var bus = container.Resolve<IBusControl>();
var busHandle = bus.StartAsync();
var properties = new AppProperties(app.Properties);
if (properties.OnAppDisposing != CancellationToken.None)
{
properties.OnAppDisposing.Register(() => busHandle.Result.StopAsync(TimeSpan.FromSeconds(30)));
}
}
}
// Controller
public IHttpActionResult Post()
{
_bus.Publish<IFooMessage>(new
{
Foo = "Foo"
});
return Ok();
}
And this is the relevant Consumer code:
// Startup.cs
public class Startup
{
public void Configuration(IAppBuilder app)
{
HttpConfiguration config = new HttpConfiguration();
IContainer container = null;
var builder = new ContainerBuilder();
builder.RegisterType<FooService>().As<IFooService>().InstancePerRequest();
builder.RegisterModule<BusModule>();
builder.RegisterModule<ConsumersModule>();
// Register Web API controllers
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
// Resolve dependencies
container = builder.Build();
config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
WebApiConfig.Register(config);
SwaggerConfig.Register(config);
app.UseCors(CorsOptions.AllowAll);
// Register the Autofac middleware FIRST.
app.UseAutofacMiddleware(container);
app.UseWebApi(config);
// Starts MassTransit Service bus, and registers stopping of bus on app dispose
var bus = container.Resolve<IBusControl>();
var busHandle = bus.StartAsync();
var properties = new AppProperties(app.Properties);
if (properties.OnAppDisposing != CancellationToken.None)
{
properties.OnAppDisposing.Register(() => busHandle.Result.StopAsync(TimeSpan.FromSeconds(30)));
}
}
}
// BusModule.cs
public class BusModule : Module
{
protected override void Load(ContainerBuilder builder)
{
builder.Register(context =>
{
var busControl = Bus.Factory.CreateUsingRabbitMq(cfg =>
{
IRabbitMqHost rabbitMqHost = cfg.Host(new Uri(ConfigurationManager.AppSettings["RabbitMQHost"]), settings =>
{
settings.Username(ConfigurationManager.AppSettings["RabbitMQUser"]);
settings.Password(ConfigurationManager.AppSettings["RabbitMQPassword"]);
});
cfg.ReceiveEndpoint(rabbitMqHost, "IP.AgilePoint.queue", ec =>
{
ec.LoadFrom(context);
});
});
return busControl;
})
.SingleInstance()
.As<IBusControl>()
.As<IBus>();
}
}
// ConsumerModule.cs
public class ConsumersModule : Module
{
protected override void Load(ContainerBuilder builder)
{
builder.RegisterType<FooConsumer>();
}
}
// FooConsumer.cs
public class FooConsumer : IConsumer<IFooMessage>
{
private IFooService _service;
public FooConsumer(IFooService service)
{
_service = service;
}
public Task Consume(ConsumeContext<IFooMessage> context)
{
IFooMessage @event = context.Message;
_service.DoStuff(@event.Foo);
return Task.FromResult(context.Message);
}
}
Note my FooConsumer has a dependency (constructor) on IFooService. I've followed Masstransit documentation but I can't get this to work. What am I doing wrong?
Framework versions:
Updated:
Code can be found in this Github repository
I'd suggest looking at the documentation specific to Autofac, it's a fully supported container via the extension library.
http://masstransit-project.com/MassTransit/usage/containers/autofac.html
The package: https://www.nuget.org/packages/masstransit.autofac
Finally I found what I was doing wrong. For some reason I couldn't see my queues in RabbitMQ Management. When I have been able to see the error queue, I noticed de following error:
I was registering my IFooService in this way:
builder.RegisterType<FooService>().As<IFooService>().InstancePerRequest();
The InstancePerRequest()
was causing the error. If I register the service with builder.RegisterType<FooService>().As<IFooService>()
everything works fine. I Think this is because my bus instance is working as singleton (registered as SingleIsntace()
). The fact of using a web api project to host my bus/consumers caused me confusion.
Anyway, thanks to @Chris Patterson and @Alexey Zimarev for pointint me in the right direction of implementation (using MT extension to register consumers).
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.