DotNet Core 6 and ApiController with scopped services for Db Context need Async/await? - asp.net-core

I am not sure if the Await/Asyn method is needed in API Controller with scoped service injection?
For example, I got a controller that returns a list of users. The controller action injects a userService then call a function. The userService then inject my DbContext and ask for users in the sql DB.
I see many demos without any Asycn/Await on the server side. I read somewhere that the gain of performance is minor in a scoped service task and if I got a very long task, only the scoped service will be blocked.
But I am not sure of that. Any advice on that?
My client side is angular and the HTTP post or Get are asynchronous, but I am wondering if I need to keep async all the way down the controller->Service to be sure of maximum performance.

Related

Correct way to clean up a "Pre" instance of ServiceCollection and ServiceProvider?

I am implementing a Custom Configuration Provider in my application.
In that provider, I have to make a REST API call. That call needs a valid OAuth 2 Token to succeed. To get that token I need a semi complicated tree of class dependencies.
For the rest of my application, I just use dependency injection to get the needed instance. But a custom configuration provider is called well before dependency injection is setup.
I have thought about making a "Pre" instance of dependency injection. Like this:
IServiceCollection services = new ServiceCollection();
// Setup the DI here
IServiceProvider serviceProvider = services.BuildServiceProvider();
var myTokenGenerator = serviceProvider.GetService<IMyTokenGenerator>();
But I have read that when you make another ServiceCollection, it can cause problems. I would like to know the way to avoid those problems.
How do I correctly cleanup a "pre-DI" instance of ServiceCollection and ServiceProvider?
(Note: Neither one seems to implement IDisposable.)
Hm, I don't get the point why you want to do it that way.
I'd probably get the Serviceprovider fully build.
To avoid that retrieved services affect each other I'd would use nested containers/scopes which means that if you retrieve retrieve the same service you get different instances per container/scope.
Hopefully I understood what you want to achieve.
See
.NET Core IServiceScopeFactory.CreateScope() vs IServiceProvider.CreateScope() extension

Appropriate approach to track database changes in a .Net Core Web API and send corresponding push notification to client using SignalR

I have a project in .net core 5 Web API which is using EF Core as ORM. I would like to send notification to specific/all clients whenever any successful insert/update/delete is performed on specific tables in the database. This Web API project would be the only way to access the database.
To send push notification, I am using SignalR.
Due to performance related issues I do not intend to use trigger, change tracker etc mechanisms that are directly associated with the database.
Any action method in my web api controller would have the following flow -
EmployeeService : BaseService {
...
}
EmployeeController:BaseController {
private EmployeeService empService;
...
[HttpPost]
public Task<EmployeeDto> EditEmployee(Guid id, EmployeeUpdateDto model) {
....
// Here I call the corresponding method in EmployeeService which in turn calls appropriate
// Repository method
..
}
}
So in controller method , after the appropriate service call, I would be able to understand whether the table has been actually updated or not and accordingly I can call SignlaR to send push notification.
My query is whether this is the best approach to handle the scenario ?
And if it is the best approach then shall I use a ResultFilter or another service (that I inject in Every Controller ) to send the SignalR notification.
In case this approach does not seem to be an efficient one, please suggest how can I achieve the same in an alternate manner.

¿Is there a way to call a class method on every controller action?

I'm implementing a cache system to handle my JWT on server side to emulate a Session State , everytime an action is called i must validate the token on the server cache to see if it's still valid, is there a way to create a something like
[Authorize] or [AllowAnonymous]
To search over the request and do whatever is needed to valide it? i already have a singleton class that handles the cache system, all i need is an easy way to call the right methods.
I want to avoid calling via Dependency Injection the method on every action on every method.
I'm using Net Core 3.0, Distributed Cache, and a Web API with JWT validation.
Thank you.
You need to implement an Action Filter. See the documentation for more details

Multi-tenant .Net Core Web API

I have a requirement to build a Web API for an existing system. There are various agencies throughout the country, and each agency has its own database. All databases are on one single server. All databases are identical in structure. All databases have their own username and password. An agency has one or more users. A user can belong to one or more agencies. There is also one special database which contains a table of all users, a table of all agencies, and user-agencies bridge table.
Currently they are using a traditional Windows desktop application. When a user sets up this Windows program, they log in with a username and password. The system then displays for them a list of all the agencies that they belong to (normally just one, but some "power users" can belong to a few). They pick an agency, and then the program connects to the correct database. For the remainder of the session, everything that the user does will be done on that database.
The client wants to create a web app to eventually replace the Windows program (and the two will be running side by side for a while). One developer is creating the front end in Angular 5, and I am developing the API in ASP .Net Core 2.1.
So the web app will function in a similar manner to the Windows app. A user logs in to the web app. The web app, which consumes my Web API, tells the API which user just logged in. The API then checks which agency(s) this user belongs to from that database that stores that data. The API returns the list of agencies the user belongs to to the web app. There, the user picks an agency. From this point on, the web app will include this Agency ID in the header of all API calls. The API, when it receives a request from the web app, will know which database to use, based on the Agency ID in the header of the request.
Hope that makes sense...
Obviously this means that I will have to change the connection string of the DbContext on the fly, depending on which database the API must talk to. I've been looking at this, firstly by doing it on the controller itself, which worked but would involve a lot of copy-and-paste anti-patterns in all my controllers. So I am trying to move this to the DbContext's OnConfiguring event. I was thinking it'd be best to create a DbContext Factory to create the DbContexts, using the appropriate connection string. I'm just a bit lost though. You see, when the web app calls an end point on the web api (let's say an HTTP GET request to get a list of accounts), this will fire the HttpGet handler in the Accounts controller. This action method then reads the Agency ID header. But this is all happening on the controller.... If I call the DbContext Factory from the DbContext's OnConfiguring() event, it would have to send the Agency ID (which was read in the controller) to the factory so that the factory knows which connection string to create. I'm trying not to use global variables to keep my classes loosely coupled.
Unless I have some service running in the pipeline that intercepts all requests, reads the Agency ID header, and this somehow gets injected into the DbContext constructor? No idea how I would go about doing this...
In summary, I'm a bit lost. I'm not even sure if this is the correct approach. I've looked at some "multi-tenant" examples, but to be honest, I've found them a bit hard to understand, and I was hoping I could do something a bit simpler for now, and with time, as my knowledge of .Net Core improves, I can look at improving the code correspondingly.
I am working on something similar you describe here. As I am also quite at the start, I have no silver bullet yet. There is one thing where could help you with your approach though:
firstly by doing it on the controller itself, which worked but would involve a lot of copy-and-paste anti-patterns in all my controllers.
I took the approach of having a middleware being in charge of swapping the dbconnection string. Something like this:
public class TenantIdentifier
{
private readonly RequestDelegate _next;
public TenantIdentifier(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext httpContext, GlobalDbContext dbContext)
{
var tenantGuid = httpContext.Request.Headers["X-Tenant-Guid"].FirstOrDefault();
if (!string.IsNullOrEmpty(tenantGuid))
{
var tenant = dbContext.Tenants.FirstOrDefault(t => t.Guid.ToString() == tenantGuid);
httpContext.Items["TENANT"] = tenant;
}
await _next.Invoke(httpContext);
}
}
public static class TenantIdentifierExtension
{
public static IApplicationBuilder UseTenantIdentifier(this IApplicationBuilder app)
{
app.UseMiddleware<TenantIdentifier>();
return app;
}
}
Here I am using a self-created http-header called X-Tenant-Guid to identify the tenants GUID. Then I make a request to the global Database, where I do get the connection string of this tenants db.
I made the example public here. https://github.com/riscie/ASP.NET-Core-Multi-Tenant-multi-db-Example (it's not yet updated to asp net core 2.1 but it should not be a problem to do so quickly)

ServiceStack and NHibernate Unit Of Work Pattern

Long story as brief as possible...
I have an existing application that I'm trying to get ServiceStack into to create our new API. This app is currently an MVC3 app and uses the UnitOfWork pattern using Attribute Injection on MVC routes to create/finalize a transaction where the attribute is applied.
Trying to accomplish something similar using ServiceStack
This gist
shows the relevant ServiceStack configuration settings. What I am curious about is the global request/response filters -- these will create a new unit of work for each request and close it before sending the response to the client (there is a check in there so if an error occurs writing to the db, we return an appropriate response to the client, and not a false "success" message)
My questions are:
Is this a good idea or not, or is there a better way to do
this with ServiceStack.
In the MVC site we only create a new unit
of work on an action that will add/update/delete data - should we do
something similar here or is it fine to create a transaction only to retrieve data?
As mentioned in ServiceStack's IOC wiki the Funq IOC registers dependencies as a singleton by default. So to register it with RequestScope you need to specify it as done here:
container.RegisterAutoWiredAs<NHibernateUnitOfWork, IUnitOfWork()
.ReusedWithin(ReuseScope.Request);
Although this is not likely what you want as it registers as a singleton, i.e. the same instance returned for every request:
container.Register<ISession>((c) => {
var uow = (INHibernateUnitOfWork) c.Resolve<IUnitOfWork>();
return uow.Session;
});
You probably want to make this:
.ReusedWithin(ReuseScope.Request); //per request
.ReusedWithin(ReuseScope.None); //Executed each time its injected
Using a RequestScope also works for Global Request/Response filters which will get the same instance as used in the Service.
1) Whether you are using ServiceStack, MVC, WCF, Nancy, or any other web framework, the most common method to use is the session-per-request pattern. In web terms, this means creating a new unit of work in the beginning of the request and disposing of the unit of work at the end of the request. Almost all web frameworks have hooks for these events.
Resources:
https://stackoverflow.com/a/13206256/670028
https://stackoverflow.com/search?q=servicestack+session+per+request
2) You should always interact with NHibernate within a transaction.
Please see any of the following for an explanation of why:
http://ayende.com/blog/3775/nh-prof-alerts-use-of-implicit-transactions-is-discouraged
http://www.hibernatingrhinos.com/products/nhprof/learn/alert/DoNotUseImplicitTransactions
Note that when switching to using transactions with reads, be sure to make yourself aware of NULL behavior: http://www.zvolkov.com/clog/2009/07/09/why-nhibernate-updates-db-on-commit-of-read-only-transaction/#comments