I am developing an application with multiple tenants. Each tenant can be associated with a user to identify the database that it will have access to, through the connection string that is stored in the database.
The problem I am having is that I only identify this connection string at the moment the user logs in, however I need to register this connection string when the StartUp class is executed.
I tried to do this using session variables, I got the ConfigureServices method of the StartUp class to run again with the correct value, but I can not get this new configuration to take effect.
services.AddScoped<IDapperContext>(s => new DapperContext(connectionString));
I guess I need to rebuild for the new setting to take effect.
How can I do this?
Am I on the right path?
Is there any other way to solve this problem?
I recently read this article, which talks about injecting the HTTPContext into your service.
https://www.strathweb.com/2016/12/accessing-httpcontext-outside-of-framework-components-in-asp-net-core/
Once you have the context, you can get the authenticated user, and retrieve your connection string from a second DB or source that maps users to databases. You would have to configure your context options during construction of the context, in order to control the connection string for the context as a scoped service.
You might want to consider using a context factory instead that does this for you.
The code in startup.cs would add a context for the database with your connection strings, and then your factory would accept that as an injected dependency. Your factory would also take in IHttpContextAccessor as a dependency giving you access to the user in the context. Together you could then obtain the connection string, and wire up the DbContextOptions to pass to a new instance of your context.
This seems like the easiest approach for DI to me.
Related
How would you configure the middleware to change the DBContext connection string based on a sub-domain of the income request?
It appears that the DBContext is set in the Startup... which looks too early to determine the HTTPRequest to resolve the connection string.
Well, this might not suit your needs entirely, but here's what I would do:
Create a DbContextFactory class. This DbContextFactory class can create instances of the DbContext and can pass in any string to the DbContext constructor. Then inject this factory and whenever you need an instance of the dbcontext, just ask the factory to return one for you. Of course you have to manage the lifetime of the created contexts yourself (i.e. using block).
Another option can be to create the DbContextFactory so that it holds an instance of a DbContext. When you ask for a context object from the factory, the factory creates a new one and also stores it in a private field, and subsequent calls return that same instance. Make the factory IDisposable and in its Dispose() method, dispose the context as well. This way you don't have to worry about managing lifetime (if you use a Scoped registration).
I am in a situation where requirement is to keep an application level object in web api which can be accessed by all requests. I know one can use HttpContext.Current but that is not required since HttpContext is only for the liftime of request. I need a solution where i can keep an object that all requests can access and update as required.
Use a static class to hold your application level objects. static classes and static data members are created once for the application lifetime and all ASP.NET requests can access them.
I learnt it the hard way. Some time back, I mistakenly created a static field to hold customer-specific database connection string, in a ASP.NET Web API project and it became a mess. On each customer's login it was being set (overridden) in the code and the requests from the previously logged customers were using this newly set static SQL connection string for their queries. It was an embarrassing situation when customer's inadvertently saw each other's data.
You could use SessionState (per session).
I.e.
Session["YourDataKey"] = ApplicationLevelObject;
And then check the session state variable on each request that requires it.
However if you require the object for longer, I.e. every single user session, then I would suggest persisting your object to a database. You could use an ORM such as Entity Framework.
Cheers
We're writing a class we'll use in our asp.net site. This class will pull down some json using HttpClients and such, and use it to provide information to other clients.
Some of this information will change very infrequently and it doesn't make sense to query for it on each client request.
For that reason I'm thinking of making a static constructor in this new class for the slow-changing information and stashing the results in a few static member variables. That'll save us a few HttpRequests down the line-- I think.
My question is, how long can I expect that information to be there before the class is recycled by ASP.Net and a new one comes into play, with the static constructor called once more? Is what I'm trying to do worth it? Are there better ways in ASP.Net to go about this?
I'm no expert on ASP.Net thread pooling or how it works and what objects get recycled and when.
Typical use of the new class (MyComponent, let's call it) would be as below, if that helps any.
//from mywebpage.aspx.cs:
var myComponent = new MyComponent();
myComponent.doStuff(); //etc etc.
//Method calls like the above may rely on some
//of the data we stored from the static constructor call.
Static fields last as long as the AppDomain. It is a good strategy that you have in mind but consider that the asp runtime may recycle the app pool or someone may restart the web site/server.
As an extension to your idea, save the data locally (via a separate service dedicated to this or simply to the hard drive) and refresh this at specific intervals as required.
You will still use a static field in asp.net for storing the value, but you will aquire it from the above local service or disk ... here I recommend a System.Lazy with instantiation and publication options on thrread safe (see the constructor documentation).
At some point in the life cycle of an authenticated ASP.NET request the IdentityUser is retrieved from the backing store (either Entity Framework or otherwise). I'd like to hook into that process. The reason is that the user has some collection properties and I'd like to retrieve those as well with one call to the database (using IQueryable<T>.Include).
Is this possible in ASP.NET identity?
I think you probably want to implement a ClaimsAuthenticationManager
The claims authentication manager provides a place in the claims processing pipeline for applying processing logic (filtering, validation, extension) to the claims collection in the incoming principal before execution reaches your application code.
Since what you're looking for sounds like extension to me. You override the Authenticate method that has this signature:
public virtual ClaimsPrincipal Authenticate(
string resourceName,
ClaimsPrincipal incomingPrincipal
)
You probably want to override UserStore and override all of the FindXXX methods that return a User do add whatever Includes that you wanted.
I got a webapp that stores a config object in ApplicationState.
This object contains the connection string to the database among other things.
Sometimes i start a async thread to do a few longer running tasks, like sending emails and updating the database.
However since this thread don't have a HttpContext i can't get at the config object.
I know this design that everything depends on HttpContext is bad, but thats too late to change now.
Looking at reflector i see that the HttpContext class just uses a static internal class to get the ApplicationState. Is there any other way to get at it?
All those internal classes in .net are really annoying.
Just pass whatever you like to your thread when you start it. Use a ParameterizedThreadStart delegate to start it instead of just a ThreadStart delegate. You could either pass it HttpContext.Current, or else bundle together the information you want your thread to have, and pass it.
If you really need access to Application State (or similar) from async handlers you should modify your HttpApplication subclass (e.g. Global.asax) to store the Application State instance (this.Application) to a static property during Application_Start:
public static HttpApplicationStateWrapper State { get; private set; }
protected void Application_Start()
{
State = new HttpApplicationStateWrapper(this.Application);
}
It would be more appropriate to use a DI framework to register this instance, but if you have one available you could probably avoid the use of Application State altogether for storing config. Further, there is a configuration framework in .NET that directly addresses this need and provides the ability to read configuration from anywhere.