How to configure NServiceBus with two RavenDB IDocumentStores? - nservicebus

In NSB 5, how do I correctly configure NSB with autofac container with one IDocumentStore for NSB data and a separate IDocumentStore for application data? I've pasted the relevant part of EndpointConfig below:
// Raven DataStore for Freight system
var appDataStore = new DocumentStore {
ConnectionStringName = "RavenDB",
DefaultDatabase = "ApplicationData"
};
appDataStore .Initialize();
// Raven DataStore for NServiceBus
var nsbDataStore = new DocumentStore
{
ConnectionStringName = "NServiceBus.Persistence",
DefaultDatabase = "BookingProcessing"
};
nsbDataStore.Initialize();
// Set up and build AutoFac container
var builder = new ContainerBuilder();
builder.RegisterInstance<DocumentStore>(appDataStore ).As<IDocumentStore>().SingleInstance();
var container = builder.Build();
// Set up NServiceBus
configuration.UseContainer<AutofacBuilder>(customizations => customizations.ExistingLifetimeScope(container));
configuration.UsePersistence<RavenDBPersistence>().SetDefaultDocumentStore(nsbDataStore);
I know this isn't working since I had problems storing sagas in another question. The SagaPersister tried to persist saga in appDataStore, but the Timeout Messages was persisted in nsbDataStore.

This issue is now fixed in NServiceBus.RavenDB v2.0.1

This is a sample for 4.x using unit of work,
If you use
Look here to see how you can implement IManageUnitsOfWork
The Init is here
Look here for the usage
will this help?

Related

How to use .net6 to operate redis?

I upgraded to the latest .net6 version, but how to configure the connection service, I can't find the entry. Can I still use the previous Startup.cs configuration in .net6? Any help is greatly appreciated!I have read the documentation, but it didn't help me:https://learn.microsoft.com/en-us/dotnet/core/compatibility/6.0
1. You can register redis service like below.
builder.Services.AddStackExchangeRedisCache(options =>
{
options.Configuration = "jason******FebB5A=,ssl=True,abortConnect=False";
});
And you can use redis in your controller, like below:
public HomeController(ILogger<WeatherForecastController> logger, CosmosClient client,IDistributedCache distributedCache)
{
_logger = logger;
_client = client;
_distributedCache = distributedCache;
}
And the test result like below:

ASP.NET Core 3 - Is it possible to add a SignalR service in Configure method when dependencies required for a factory method are available?

I am learning ASP.NET core and struggling trying to inject some ILogger instances required as parameters within a factory method used within my AddJsonProtocol of the AddSignalR method. See code below.
The JsonConvertersFactory factory method creates the JsonConverters for serialization/deserialization in signalR. It is used within the .AddJsonProtocol anonymous method when adding SignalR service.
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
services.AddServerSideBlazor();
services.AddHostedService<MqttKafkaBridge>();
services.AddHostedService<ConsumerService>();
services.AddLogging();
// how can I retrieve ILogger<MotionDetection>, ILogger<MotionInfo>, ILogger<JsonVisitor>?
services.AddSignalR(o => o.EnableDetailedErrors = true)
.AddJsonProtocol(options =>
{
options.PayloadSerializerOptions = JsonConvertersFactory.CreateDefaultJsonConverters(LoggerMotionDetection, LoggerMotionInfo, LoggerJsonVisitor);
});
services.AddCustomConfiguration(services);
}
I could build a temporary service provider and add logger dependencies so that the SignalR Json protocol could be configued. However I am not sure if this is considered an anti-pattern....
var sp = services.BuildServiceProvider();
var loggerMD = sp.GetService<ILogger<MotionDetection>>();
var loggerMI = sp.GetService<ILogger<MotionInfo>>();
var loggerJV = sp.GetService<ILogger<JsonVisitor>>();
When I use BuildServiceProvider I receive the following warning message:
Startup.cs(53,22): warning ASP0000: Calling 'BuildServiceProvider' from application code results in an additional copy of singleton services being created. Consider alternatives such as dependency injecting services as parameters to 'Configure'.
Is it possible to add a service in Configure method, i.e. add the SignalR service in Configure when ILogger instances can be resolved?
OR
Is it possible to inject the SignalRService in Configure method and update it's Json protocol configuration?
Update
Tried injecting ISignalRServerBuilder in Configurebut receive an exception that could not find an ISignalRServerBuilder instance in container registry (Autofac).
Any ideas?
public void Configure(IApplicationBuilder app, ISignalRServerBuilder builder, IWebHostEnvironment env)
{
// this tries to build the options from the service container but
// the builder is null
builder.AddJsonProtocol(op =>
{
var lMD = app.ApplicationServices.GetService<ILogger<MotionDetectionConverter>>();
var lMI = app.ApplicationServices.GetService<ILogger<MotionInfoConverter>>();
var lJV = app.ApplicationServices.GetService<ILogger<JsonVisitor>>();
op.PayloadSerializerOptions = JsonConvertersFactory.CreateDefaultJsonConverters(lMD, lMI, lJV);
});
...
}

How to ensure that Entity Framework Core InMemory database is created per test method?

Dears,
I am trying to create integration tests that tests my API controller using entity framework core in-memory database provider.
I created CustomWebApplicationFactory that configure my services, including my db context according to official documentation guideline
and I used this factory as IClassFixture in my xunit test classes but my tests got broken when they run in parallel because as i think they shared the same database instance.
This is my configuration
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
builder.ConfigureServices(services =>
{
// Create a new service provider.
var serviceProvider = new ServiceCollection()
.AddEntityFrameworkInMemoryDatabase()
.BuildServiceProvider();
// Add a database context (ApplicationDbContext) using an in-memory
// database for testing.
services.AddDbContext<ApplicationDbContext>(options =>
{
options.UseInMemoryDatabase("InMemoryDbForTesting");
options.UseInternalServiceProvider(serviceProvider);
});
// Build the service provider.
var sp = services.BuildServiceProvider();
// Create a scope to obtain a reference to the database
// context (ApplicationDbContext).
using (var scope = sp.CreateScope())
{
var scopedServices = scope.ServiceProvider;
var db = scopedServices.GetRequiredService<ApplicationDbContext>();
// Ensure the database is created.
db.Database.EnsureCreated();
}
});
}
}
i think they shared the same database instance
You are correct, IClassFixture is a shared object instance across multiple tests.
What you can do to reuse the ConfigureWebHost is use the test class' constructor instead.
That way, all your tests will run the configuration but will not share object instances. You might also need to change the options.UseInMemoryDatabase("InMemoryDbForTesting"); to use a random in-memory db name (e.g. options.UseInMemoryDatabase(Guid.NewGuid().ToString());.
The official xunit docs might also help : https://xunit.net/docs/shared-context

Adding SignalR service as a singleton and then adding redis to it

Hello i have an app up and running using orleans and signalR and i use a HubConnectionBuilder to initialize my SignalRClient like this
public async Task<HubConnection> InitSignalRCLient()
{
Program.WriteConsole("Starting SignalR Client...");
var connection = new HubConnectionBuilder()
.ConfigureLogging(logging =>
logging
.AddProvider(new LogProvider(Log.logger, new LogProviderConfiguration
{
Category = LogCategory.SignalR,
Level = LogLevel.Warning
}))
)
.WithUrl(Configuration.GetConnectionString("SignalRInterface"))
.Build();
And then i add the service as a singleton in the configure service
services.AddSingleton(SignalRClient)
The problem is now that i want to use redis as a backplane to this and i am having issues adding the redis service to my current way of using SignalR
like this doesn't work
services.AddSingleton(SignalRClient).AddStackExchangeRedis();
according to the documentation https://learn.microsoft.com/en-us/aspnet/core/signalr/redis-backplane?view=aspnetcore-2.2 it wants you to add it like
services.AddSignalR().AddStackExchangeRedis("<your_Redis_connection_string>");
but that doesn't work with how i use SignalR. Is there anyway to get my implementation to work or anyone got any advice on how to tackle this?
Try to add in ConfigureServices this:
services.AddDistributedRedisCache(option =>
{
option.Configuration = Configuration.GetConnectionString(<your_Redis_connection_string>);
});
services.AddSignalR().AddStackExchangeRedis(Configuration.GetConnectionString(<your_Redis_connection_string>));
Also add this in Configure
app.UseSignalR(routes =>
{
routes.MapHub<your_Hub>("/yourHub");
});
And don't forget add abortConnect=False in connectionStrings

How can I configure a webservice in .NET 4 without using app.config

I have a .NET 4 project made of a EXE project and a class library. The class library contains a reference to a webservice (using WCF).
Everything works ok only if I have deployed the app.config file (that contains the info about the binding) along with my exe. How can I have everything configured by code without the need to deploy an app.config file (I don't want my users to change those settings).
Thank you.
Andrea
You can use the ChannelFactory class to generate proxies to your services.
Everything you configure through the configuration file can also be done using code.
You just need to instantiate an instance of the correct binding and configure its properties according to the service requirements on the other side.
For example:
private IDisposableService GetClient()
{
var netBinding = new BasicHttpBinding();
netBinding.Security.Mode = BasicHttpSecurityMode.TransportCredentialOnly;
netBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Ntlm;
var factory = new ChannelFactory<IDisposableService>(netBinding, new EndpointAddress(new Uri(ServerUrl)));
factory.Credentials.Windows.AllowedImpersonationLevel = TokenImpersonationLevel.Impersonation;
factory.Credentials.Windows.ClientCredential = CredentialCache.DefaultNetworkCredentials;
var channel = factory.CreateChannel();
return channel;
}
interface IDisposableService : IYourService, IDisposable
{
}
Then you can simply use:
using (var proxy = GetClient())
{
// call proxy here
}
This is how I did it:
MyServiceResponseClient embEvalServiceClient = new MyServiceResponseClient (new BasicHttpBinding(),
new EndpointAddress(new Uri(url)));
if (embEvalServiceClient != null)
{
embEvalServiceClient.GetPendingEvalsCompleted += getPendingEvalsCompletedHandler;
embEvalServiceClient.GetPendingEvalsAsync(attemptId);
}