3

My web api follows this structure

/countrycode/mycontroller e.g. /gbr/mycontroller I am using middleware to get the country code so I can switch connection string:

public class ConnectionMiddleware
{

public ConnectionMiddleware(RequestDelegate next)
{
    this.next = next;
}

private readonly RequestDelegate next;

public async Task InvokeAsync(HttpContext httpContext)
{            
    var values = httpContext.GetRouteData().Values;            
    await next(httpContext);
}

}

So now I have my country code I want to set the connection string property in my db service.

My db service is already registered in Startup.cs:

services.AddTransient<INpgSqlDataAccess, NpgSqlDataAccess>();

Can the connection string be set via my middleware now and be seen globally (after already being registered) or should I register the service in my middleware?

3
  • Is CountryCode different in every requests? Commented Jul 20, 2020 at 17:37
  • Yes, it is sent per request Commented Jul 20, 2020 at 17:38
  • 1
    How about services.AddHttpContextAccessor().AddTransient<INpgSqlDataAccess>(provider => { var httpContext = provider.GetService<IHttpContextAccessor>().HttpContext; return ...})? Commented Jul 20, 2020 at 17:39

2 Answers 2

3

First you should create a class for manage connection string.

public interface IDatabaseConnectionManager
{
    void SetConnectionString(string connectionString);
    string GetConnectionString();
}

public class DatabaseConnectionManager
{
    private string _connectionString;

    public DatabaseConnectionManager()
    {
        // _connectionString = DefaultConnectionString;
    }

    public void SetConnectionString(string connectionString)
    {
        this._connectionString = connectionString;      
    }

    public void GetConnectionString() {
        return _connectionString; 
    }
}

And then if you want to use middleware you can try this:

public class ConnectionMiddleware { private readonly RequestDelegate _next;

public async Task InvokeAsync(HttpContext httpContext,IDatabaaseConnectionManager connectionManager)
{
    var connectionString = "some-connection-string"; // Create Your Connection String Here

    connectionManager.SetConnectionString(connectionString);

    await _next.InvokeAsync(httpContext);
}

And in your Startup:

public void ConfigureServices(IServiceCollection services)
{
    services.AddScoped<IDatabaseConnectionManager,DatabaseConnectionManager>();
    services.AddScoped<INgpSqlDataAccess>(options=>
    {
        var connectionManager = options.GetService<IDatabaseConnectionManager>();
        var connectionString = connectionManager.GetConnectionString();

        // Create Your SqlDataAccess With ConnectionString
        return new NgpSqlDataAccess(connectionString);
    });
}

Every time you resolve INgpSqlDataAccess you get a new instance with your desired connectionstring. Be carefull that you must register your dependencies with per http request life time (Scoped).

Sign up to request clarification or add additional context in comments.

2 Comments

Cheers for this!
do you have any idea why what I set in middleware is not there when I resolve the service?, it is set as scoped.
0

If your DbContext is called AppDbContext, you can modify the connection string in middleware like this:

public async Task Invoke(
    HttpContext httpContext,
    IConfiguration configuration,
    AppDbContext context)
{
    context.Database.SetConnectionString(configuration.GetConnectionString("Other"));

    await _next(httpContext);
}

In Startup.ConfigureServices:

services.AddDbContext<AppDbContext>(options =>
    options.UseNpgsql(Configuration.GetConnectionString("Default")));

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.