I am having trouble getting IUniformSession to work in an Azure WebJobs SDK project with Generic Host. I am using .NET built-in DI. I have created a compact repro found below.
I am using
- NServiceBus 7.7.4
- NServiceBus.Extensions.Hosting 1.1.0
- NServiceBus.UniformSession 2.2.0
- Microsoft.Azure.WebJobs 3.0.33
- .NET 6
Expected behavior
IUniformSession is resolved as a dependency when classes ("jobs") are instantiated.
Actual behavior
IUniformSession always resolves to NULL. Some quick asserts (as seen below) indicate IUniformSession being registered in the DI container, so the .EnableUniformSession() is doing that correctly, but when an instance is requested it always resolves to NULL.
Steps to reproduce
csproj
<ItemGroup>
<PackageReference Include="Microsoft.Azure.WebJobs" Version="3.0.33" />
<PackageReference Include="Microsoft.Azure.WebJobs.Extensions" Version="4.0.1" />
<PackageReference Include="Microsoft.Azure.WebJobs.Extensions.Storage" Version="5.0.1" />
<PackageReference Include="Microsoft.Azure.WebJobs.Host.Storage" Version="4.1.0" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="6.0.1" />
<PackageReference Include="NServiceBus" Version="7.7.4" />
<PackageReference Include="NServiceBus.Extensions.Hosting" Version="1.1.0" />
<PackageReference Include="NServiceBus.UniformSession" Version="2.2.0" />
<PackageReference Include="Serilog" Version="2.11.0" />
<PackageReference Include="Serilog.Extensions.Hosting" Version="5.0.1" />
<PackageReference Include="Serilog.Sinks.Console" Version="4.0.1" />
</ItemGroup>
Program.cs
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using NServiceBus;
using NServiceBus.UniformSession;
using NSUniformSessionRepro.DemoClasses;
using Serilog;
// Setup the ability to read config files
var configurationBuilder = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
// then read the environment variables (in Azure) which will override some settings from the local settings
.AddEnvironmentVariables();
var configuration = configurationBuilder.Build();
var builder = new HostBuilder();
builder
.UseSerilog(Log.Logger)
.ConfigureAppConfiguration((context, config) =>
{
config.AddConfiguration(configuration);
})
.ConfigureWebJobs(b =>
{
b.AddAzureStorageCoreServices()
.AddAzureStorageBlobs()
.AddAzureStorageQueues()
.AddTimers();
});
IServiceCollection _serviceCollection = null;
builder.ConfigureServices(services =>
{
services.AddTransient<IMessagingService, MessagingService>();
_serviceCollection = services;
});
builder.UseNServiceBus(context =>
{
var endpointConfiguration = new EndpointConfiguration("MyEndpoint");
endpointConfiguration.EnableUniformSession();
endpointConfiguration.UseTransport<LearningTransport>();
endpointConfiguration.UsePersistence<LearningPersistence>();
// configure endpoint here
return endpointConfiguration;
});
var host = builder.Build();
var isUniformSessionRegistered = _serviceCollection.Any(x => x.ServiceType == typeof(IUniformSession));
Console.WriteLine("UniformSession is registered in DI: " + isUniformSessionRegistered);
using (host)
{
await host.RunAsync();
}
static void ConfigureLogging(IConfigurationRoot configuration)
{
var loggerConfiguration = new LoggerConfiguration()
.MinimumLevel.Information()
.WriteTo.Console();
Log.Logger = loggerConfiguration
.CreateLogger();
}
MessagingService.cs (just a dummy class that itself has a dependency on IUniformSession)
public interface IMessagingService
{
// public for testing
IUniformSession UniformSession { get; set; }
Task Send(object message);
}
public class MessagingService : IMessagingService
{
// public for testing
public IUniformSession UniformSession { get; set; }
public MessagingService(IUniformSession uniformSession)
{
UniformSession = uniformSession;
}
public async Task Send(object message)
=> await UniformSession.Send(message);
}
DemoJob
public class DemoJob
{
private readonly IMessagingService _messagingService;
public DemoJob(IMessagingService messagingService)
{
_messagingService = messagingService;
}
public void DummyJob([TimerTrigger("0 0 12 * * *", RunOnStartup = true, UseMonitor = false)] TimerInfo timer, TextWriter log)
{
// no-op
// for testing puporses
if (_messagingService.UniformSession == null)
Console.Write("UniformSession was NULL");
}
}
Any help would be massively appreciated.