Search code examples
asmxnservicebus

Using NServiceBus with an ASMX web service


I have legacy code base running a .Net 4.8 ASMX web service (not WCF based). I need to send messages using NServiceBus, but I cannot find a way to resolve any of the NServiceBus objects that I need (ITransactionalSession, IMessageSession). This is straightforward in a modern application using DI, but I am stuck in legacy land where that is non-existent. Ideally, I want to also take advantage of features like the outbox and transactional messaging to prevent ghost messages and zombie records.

I found this example from David Boike (a developer at Particular), but it is over 12 years (and 6 versions) old, so I'm hesitant to follow it too closely. I am still reviewing it to see what I can glean, but I'm hoping that this community can provide some more up-to-date suggestions.

I am currently pulling in NSB 8.x (the most recent), but I would be willing to consider downgrading to a previous version if it supports .asmx services better while still minimizing any security considerations.

Update: Thanks to Dennis pointing out self-hosting below, I found Externally Managed Mode which allows me to create the service collection and manage its lifetime. I think this sample is still non-transactional (i.e. no transactional session/outbox support), and I do not understand why the message session is registered as a singleton instead of as a scoped dependency.

This is what my code currently looks like:

const string endpointName = "MyEndpoint";
var endpoint = new EndpointConfiguration(endpointName);
// ... other configurations
var persistence = endpoint.UsePersistence<SqlPersistence>();
persistence.SqlDialect<SqlDialect.MsSqlServer>();
persistence.ConnectionBuilder(() => new SqlConnection(connectionString));
persistence.EnableTransactionalSession();
endpoint.EnableOutbox();

var services = new ServiceCollection();
var startable = EndpointWithExternallyManagedContainer.Create(endpoint, services);
var serviceProvider = services.BuildServiceProvider(new ServiceProviderOptions
            {
                ValidateOnBuild = true
            });

services.AddSingleton(p => startable.MessageSession.Value);
_endpointInstance = startable.Start(serviceProvider).ConfigureAwait(false).GetAwaiter().GetResult();

Is there anything wrong with registering the MessageSession as a scoped dependency? Or am I incorrect in my assumption that it would need to be a scoped dependency to support a transactional session/outbox?


Solution

  • You're probably looking for "self hosting". You'll end up with an IMessageSession that you can store somewhere or have it injected in places where you want it.