Being a new user of MassTransit and RabbitMQ I'm currently trying to make my ASP.NET core service to work with MassTransit.
Taking this documentation section to configure MassTransit and ASP.NET Core I'm unable to get it working.
Currently (part of) the Startup.cs looks like
services.AddMassTransit(x =>
{
x.AddConsumer<MailConsumer>();
x.AddConsumer<MailFailedConsumer>();
x.AddBus(provider => ConfigureBus(provider, rabbitMqConfigurations));
});
private IBusControl ConfigureBus(
IServiceProvider provider,
RabbitMqConfigSection rabbitMqConfigurations) => Bus.Factory.CreateUsingRabbitMq(
cfg =>
{
var host = cfg.Host(
rabbitMqConfigurations.Host,
"/",
hst =>
{
hst.Username(rabbitMqConfigurations.Username);
hst.Password(rabbitMqConfigurations.Password);
});
cfg.ReceiveEndpoint(host, $"{typeof(MailSent).Namespace}.{typeof(MailSent).Name}", endpoint =>
{
endpoint.Consumer<MailConsumer>(provider);
});
cfg.ReceiveEndpoint(host, $"{typeof(MailSentFailed).Namespace}.{typeof(MailSentFailed).Name}", endpoint =>
{
endpoint.Consumer<MailFailedConsumer>(provider);
});
});
The exchange is created automatically in RabbitMQ on startup, but no queue is bind to the exchange which I would expect.
After invoking my API endpoint I can see activity on the exchange, but of course the consumers doing nothing as there is no queue.
What (obvious) part am I missing?
Ok, I found the issue. It worked as described in the docs at the moment the docs were written. There are several AddMassTransit extensions for the IServiceCollection interface, which is confusing.
AddMassTransit overload, which accepts the bus instance works as described.
AddMassTransit overload, which accepts the Action<IServiceCollectionConfigurator> only does necessary registrations.
You need to add one line:
services.AddMassTransitHostedService();
and your code will work.
Related
.netAt the moment, this is the code I have:
var builder = WebApplication.CreateBuilder(args);
builder.Host.UseWindowsService(options => {
options.ServiceName = "My Server";
}).ConfigureServices(services => {
services.AddHostedService<WindowsBackgroundService>();
});
...
and
"profiles": {
"MyProj": {
"applicationUrl": "http://127.0.0.1:5000;",
How do I instead set applicationUrl (with port) in the builder configuration?
I saw various answers but not sure how to proceed with ASP.NET Core 7.0, here it says to use:
builder.WebHost.ConfigureKestrel(serverOptions =>
{
serverOptions.ConfigureEndpointDefaults(listenOptions =>
{
// ...
});
});
but I am not sure how to set the applicationUrl and if WebHost is what I need (as I am using a Windows service as above).
It's perfectly valid to use WebApplicationBuilder.WebHost in combination with the Windows Service functionality, as the WebHost still runs when using WebApplicationBuilder.
Because of that, I think the simplest method for setting the URL for your scenario is to use UseUrls:
builder.WebHost.UseUrls("http://127.0.0.1:5000");
This doesn't require setting anything that's specific to Kestrel, yet the configuration does make its way down to Kestrel.
To configure Kestrel directly, you can use ConfigureKestrel, as suggested in your question. To set the URL this way, use the Listen method:
builder.WebHost.ConfigureKestrel(kestrelServerOptions =>
{
kestrelServerOptions.Listen(IPAddress.Loopback, 5001);
});
There are a number of options for configuring the URL, such as configuring HTTPS, using DnsEndPoint, etc. This approach offers a lot more flexibility, but if you simply want to set the URL programmatically, I'd still recommend the UseUrls approach.
Just run the following command in cmd start-url-in-aspnet-core
setx ASPNETCORE_URLS "http://127.0.0.1:5001;https://127.0.0.1:5002"
I'm currently trying to update application that was originally .NET Core 3.1 using MassTransit 6.3.2. It is now configured to use .NET 6.0 and MassTransit 7.3.0
Our application uses MassTransit to send messages via Azure Service Bus, publishing messages to Topics, which then have other Subscribers listening to those Topic.
Cut down, it was implemented like so:
// Program.cs
services.AddMassTransit(config =>
{
config.AddConsumer<AppointmentBookedMessageConsumer>();
config.AddBus(BusControlFactory.ConfigureAzureServiceBus);
});
// BusControlFactory.cs
public static class BusControlFactory
{
public static IBusControl ConfigureAzureServiceBus(IRegistrationContext<IServiceProvider> context)
{
var config = context.Container.GetService<AppConfiguration>();
var azureServiceBus = Bus.Factory.CreateUsingAzureServiceBus(busFactoryConfig =>
{
busFactoryConfig.Host("Endpoint=sb://REDACTED-queues.servicebus.windows.net/;SharedAccessKeyName=MyMessageQueuing;SharedAccessKey=MyKeyGoesHere");
busFactoryConfig.Message<AppointmentBookedMessage>(m => m.SetEntityName("appointment-booked"));
busFactoryConfig.SubscriptionEndpoint<AppointmentBookedMessage>(
"my-subscriber-name",
configurator =>
{
configurator.UseMessageRetry(r => r.Interval(5, TimeSpan.FromSeconds(60)));
configurator.Consumer<AppointmentBookedMessageConsumer>(context.Container);
});
return azureServiceBus;
}
}
}
It has now been changed and upgraded to the latest MassTransit and is implemented like:
// Program.cs
services.AddMassTransit(config =>
{
config.AddConsumer<AppointmentBookedMessageConsumer, AppointmentBookedMessageConsumerDefinition>();
config.UsingAzureServiceBus((context, cfg) =>
{
cfg.Host("Endpoint=sb://REDACTED-queues.servicebus.windows.net/;SharedAccessKeyName=MyMessageQueuing;SharedAccessKey=MyKeyGoesHere");
cfg.Message<AppointmentBookedMessage>(m => m.SetEntityName("appointment-booked"));
cfg.ConfigureEndpoints(context);
});
// AppointmentBookedMessageConsumerDefinition.cs
public class AppointmentBookedMessageConsumerDefinition: ConsumerDefinition<AppointmentBookedMessageConsumer>
{
public AppointmentBookedMessageConsumerDefinition()
{
EndpointName = "testharness.subscriber";
}
protected override void ConfigureConsumer(IReceiveEndpointConfigurator endpointConfigurator, IConsumerConfigurator<AppointmentBookedMessageConsumer> consumerConfigurator)
{
endpointConfigurator.UseMessageRetry(r => r.Interval(5, TimeSpan.FromSeconds(60)));
}
}
The issue if it can be considered one, is that I can't bind to a subscription that already exists.
In the example above, you can see that the EndpointName is set as "testharness.subscriber". There was already a subscription to the Topic "appointment-booked" from prior to me upgrading. However, when the application runs, it does not error, but it receives no messages.
If I change the EndpointName to "testharness.subscriber2". Another subscriber appears in the Azure Service Bus topic (via the Azure Portal) and I start receiving messages. I can see no difference in the names (other than the change that I placed, in this case: the "2" suffix).
Am I missing something here? Is there something else I need to do to get these to bind? Is my configuration wrong? Was it wrong? While I'm sure I can get around this by managing the release more closely and removing unneeded queues once they're using new ones - it feels like the wrong approach.
With Azure Service Bus, ForwardTo on a subscription can be a bit opaque.
While the subscription may indeed visually indicate that it is forwarding to the correctly named queue, it might be that the queue was deleted and recreated at some point without deleting the subscription. This results in a subscription that will build up messages, as it is unable to forward them to a queue that no longer exists.
Why? Internally, a subscription maintains the ForwardTo as an object id, which after the queue is deleted points to an object that doesn't exist – resulting in messages building up in the subscription.
If you have messages in the subscription, you may need to go into the portal and update that subscription to point to the new queue (even though it has the same name), at which point the messages should flow through to the queue.
If there aren't any messages in the subscription (or if they aren't important), you can just delete the subscription and it will be recreated by MassTransit when you restart the bus.
Good day
I'm configuring Masstransit for .net6 net core application
Have added Masstransit nuget packages:
<PackageReference Include="MassTransit.Extensions.DependencyInjection" Version="7.2.4" />
<PackageReference Include="MassTransit.RabbitMQ" Version="7.2.4" />
Am registering it in Startup and it says there is no such method as AddMasstransitHostedService
I have tried publishing message without it, but no exchange is being created (and for some reason debug also shows actual address with port 0)
Would be very grateful for help
Have searched everything related on the internet, unfortunately no fixes yet
Here is the way I register Masstransit:
services.AddMassTransit(mt =>
{
mt.UsingRabbitMq((context, cfg) =>
{
cfg.Host(new Uri(RabbitMqOptions.RabbitMqUri), h =>
{
h.Username(RabbitMqOptions.UserName);
h.Password(RabbitMqOptions.Password);
});
cfg.AutoStart = true;
cfg.Publish<IServerNotificationMessage>(e => e.ExchangeType = RabbitMQ.Client.ExchangeType.Direct);
});
});
services.AddMassTransitHostedService();//<-----this one hints: IServiceCollection doesnt contain a definition for AddMassTransitHostedService...
and here is the way I've tried publishing message:
public class SomeController : ControllerBase
{
protected readonly IBus _bus;
public SomeController(IBus bus)
{
_bus = bus;
}
[HttpGet("TestPublish")]
public void TestPublish(CancellationToken cancellationToken)
{
_bus.Publish<SomeMessage>(new
{
...
... // fields go here
}, cancellationToken);
You need to add the MassTransit.AspNetCore package reference.
Note that for MassTransit V8, or later, this package is no longer required and should not be referenced.
I see that you added MassTransit v7 but MassTransit v8 has been available since .NET 6 was available. MassTransit v8 integrates a significant portion of the underlying components into a more manageable solution structure.
With MassTransit v8, Microsoft.Extensions.Hosting.Abstractions is now included, and the hosted service is registered by default. This means no more separate call to AddMassTransitHostedService and no dependency on MassTransit.AspNetCore.
The hosted service can also be configured using the standard Microsoft configuration extensions. For instance, all of the following options are optional, but can be configured.
builder.Services.AddOptions<MassTransitHostOptions>()
.Configure(options =>
{
// if specified, waits until the bus is started before
// returning from IHostedService.StartAsync
// default is false
options.WaitUntilStarted = true;
// if specified, limits the wait time when starting the bus
options.StartTimeout = TimeSpan.FromSeconds(10);
// if specified, limits the wait time when stopping the bus
options.StopTimeout = TimeSpan.FromSeconds(30);
});
I have a need to configure the MassTransit library in a way that I maintain the tags for SNS.
I can see the places to configure the Tags for the SQS Queues that are created - and that works as expected. However, I need to do a similar thing for SNS Topics that MassTransit creates.
There is a couple of things I've tried so far, unfortunately, none of them allowed me to create tags on the SNS resource.
public IBusControl GetServiceBus()
{
var serviceBus = Bus.Factory.CreateUsingAmazonSqs(sbc =>
{
sbc.Host("AmazonRegion", h =>
{
h.Config(
new AmazonSimpleNotificationServiceConfig
{
ServiceURL = _configService.AmazonSnsServiceUrl
//Tags doesn't seems the be available here
});
h.Config(new AmazonSQSConfig
{
ServiceURL = _configService.AmazonSqsServiceUrl
});
h.AccessKey("AccessKey");
h.SecretKey("SecretKey");
});
sbc.ReceiveEndpoint("queueName", e =>
{
e.Consumer<IConsumer<Message>>(_container);
e.Consumer<IConsumer<Fault<Message>>>(_container);
e.QueueTags.Add("TestTag", "DEV");
//Here I can define only Tags for the queue, not for the Topic though
});
});
serviceBus.ConnectSendAuditObservers(_messageAuditStore);
serviceBus.ConnectConsumeAuditObserver(_messageAuditStore);
return serviceBus;
}
I tried also do a manual Subscription like that:
e.Subscribe<T>(cfg =>
{
cfg.TopicTags.Add("TestTag", "test");
});
But that didn't work too.
I know there is an option to subscribe to pre-created Topics with MassTransit, but I feel that is rather a restriction, and I'd like to use the flexibility of MassTransit for managing the types.
Is there something I am missing here?
Thank you.
To configure topic tags/attributes, you need to configure the topic topology, which is done by configuring the Publish topology.
For instance, to add a tag for the Message type, you would specify:
configurator.Publish<Message>(p =>
{
p.TopicTags.Add("hello", "world");
});
I have an ASP.NET Core 2.2 MVC project and I need to set CORS policy specifically for SignalR hub but not globally (not for all controllers and actions). If I follow recommendations by adding app.UseCors() it works but globally and I need to apply the policy only for SignalR. Is there a way to do that?
I have tried this too but with no success.
EDIT 2019-07-22 18:33 CEST
Here is CORS policy I use:
services.AddCors(o =>
{
o.AddPolicy("MyCorsPolicy", b =>
{
b.AllowAnyHeader()
.AllowAnyMethod()
.SetIsOriginAllowed(s => true)
.AllowCredentials();
});
});
After hours of attempts I had to turn to GitHub and this is what Brennan Conroy suggested: https://github.com/aspnet/AspNetCore/issues/12564
And it works!
Edit 2019-07-29 13:40 CEST
This is what helped:
app.Map("/path", c =>
{
c.UseCors("somePolicy");
c.UseSignalR(route =>
{
route.MapHub<MyHub>("/hub");
});
});
And clients will connect to the hub via "/path/hub".