Configure injected services with information available in runtime - dependency-injection

I've been trying to modify injected services with values available from authenticated users.
Using the built-in DI container, I added the required service with Scoped lifetime.
services.AddScoped<ITodoRepository, TodoRepository>();
Then registered a custom middleware between authorization and MVC middlewares to modify the repository with user specific information.
// Configure authorization middleware
app.Use(async (context, next) =>
{
var todoRepository = context.ApplicationServices.GetRequiredService<ITodoRepository>();
todoRepository.UserStoreId = context.User.GetUserStoreId();
await next.Invoke();
});
// Configure MVC middleware
When the program execute a request, the injected repository within my controller does not presist the saved value.
Am i doing something wrong?
From my understanding, scoped objects are saved within request.
Also, is there another way to achieve this?

You can create your own service, i.e. IAuthenticatedUserService/AutheticatedUserService.
Into it, you inject IHttpContextAccessor.
public interface IAuthenticatedUserService
{
ClaimsPrincipal User { get; }
}
Then you inject the IAuthenticatedUserService into your repository, where you can access the logged-in user.
Of course you could also directly inject IHttpContextAccessor into your repository and access httpContextAccessor.HttpContext.User within it, but since repositories are usually defined in their own assembly, you'd also need to reference the Microsoft.AspNetCore.Http.Abstractions package from it which would cause a tight(er) coupling.
But if you don't mind this kind of coupling, just inject the IHttpContextAccessor into your repository, they are supposed to be scoped (=per request) or transient anyways.
P.S. don't forget the Dependency Injection/Inversion of Control mantra: "Don't call us, we call you". You have attempted to call "us" (the repository) to set a value.

Am i doing something wrong? From my understanding, scoped objects are saved within request.
I was able to fix the issue by replacing
context.ApplicationServices.GetRequiredService<ITodoRepository>();
with
context.RequestServices.GetRequiredService<ITodoRepository>();

Related

Dependency Injection for AzureFunction ServiceBus based on message information

I am working on AzureFunction ServiceBus v3 which handle multi-tenant message. In message I will have TenantId and I will need to register DependencyInjection per message base on this TenantId.
What I tried so far:
At StartUp, I stored the IServiceCollection as static variable
Retrieve the TenantId from the serialized message in Function'd Run method
Update IServiceCollection based on above TenantId and retrieve the Service
_serviceCollection.AddTransient<ITenantIdResolver>(ctx => { return new CompanyResolver{TenantId=tenantId}; }); var service = _serviceCollection.BuildServiceProvider().GetService<T>();
But it throw exception: Unable to resolve service for type 'Microsoft.Azure.WebJobs.Script.IEnvironment' while attempting to activate 'Microsoft.Azure.WebJobs.Script.Configuration.ScriptHostOptionsSetup' I do some research and look like it was because I used IHttpClientFactory.
How can I fix this?
Or even better if there is a way to retrieve the message in StartUp, so I can inject the tenantId properly? Like
serviceCollection.AddTransient<ITenantIdResolver>(ctx => { var tenantId = GetServicebusMessage().TenantId; return new CompanyResolver { TenantId=tenantId }; }
I think that would be the wrong order of things. Dependency injection should be setup before the message is being processed.
A resolver could be a solution. Register the resolver with the dependency injection container, and let the function be dependent on the resolver. Based on the message you get the right instance from the resolver. In this article it is explained better under "IoC Container Registration #3 – Resolver + Factory Method Pattern": https://techcommunity.microsoft.com/t5/apps-on-azure/dependency-injection-on-azure-functions-5-ways-selecting/ba-p/1502394
According to Dependency injection for azure functions, it's not possible to use the services at an early stage.
My suggestion is to change the architecture to "Durable Orchestrations" so you call an ActivityTrigger function from the orchestrator which gets back list of tenants then you fire other ActivityTriggers that will handle them.

.net core 2.0 change injected middleware settings at runtime

Hope my question will be clear. ;-)
Is it possible to change Middleware settings during runtime? I explain more.
I have following code in my configure services method in an Asp.net core 2.1 webapi
services.AddMvc(options =>
if (!securitySettings)
{
options.Filters.Add(new AllowAnonymousFilter());
}
I would like to add that filter depending on a setting in the database. Is it possible to change that during runtime or do i really need to restart my application after that setting has been changed?
Unfortunately, you can't modify the filters applied to MVC after the application has started.
However, MVC has the concept of authorization requirements, which are executed on each request. That makes them a great candidate for what you're trying to achieve.
On a high-level, we will:
change the default authorization policy to include a custom requirement;
create the class that handles this requirement, that is, determines if it's satisfied or not
Let's create the requirement class. It's empty as it doesn't need any parameters, since the result will come solely from the database:
public class ConditionalAnonymousAccessRequirement : IAuthorizationRequirement
{
}
Then we create the class that handles this requirement:
public class ConditionalAnonymousAccessHandler : AuthorizationHandler<ConditionalAnonymousAccessRequirement>
{
private readonly AppDbContext _context;
public ConditionalAnonymousAccessHandler(AppDbContext context)
{
_context = context;
}
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, ConditionalAnonymousAccessRequirement requirement)
{
if (IsAnonymousAccessAllowed())
{
context.Succeed(requirement);
}
return Task.CompletedTask;
}
private bool IsAnonymousAccessAllowed()
{
// Implementation based on the value retrieved from the database
}
}
The implementation is straightforward. If we find in the database that anonymous access is allowed, we mark this requirement as succeeded. If at least one of the requirements in a policy is satisfies, then the whole policy succeeds.
The next step is to add that requirement to the authorization policy. By default, when using an [Authorize] attribute with no parameters, MVC uses the default authorization policy, which just checks that the user is authenticated. Let's modify it to add this new requirement in the ConfigureServices method of your Startup class:
services.AddAuthorization(options =>
{
options.DefaultPolicy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.AddRequirements(new ConditionalAnonymousAccessRequirement())
.Build();
});
All looks good, but we're missing one final piece.
While we added the requirement to the policy, we haven't registered the requirement handler, which is necessary for MVC to discover it. This is again done in the ConfigureServices method.
services.AddScoped<IAuthorizationHandler, ConditionalAnonymousAccessHandler>();
While the documentation shows the handler is registered as a singleton, in this case it's better to register it per-HTTP request as it has a dependency on a DbContext which are by default registered per-HTTP request. Registering the handler as a singleton means an instance of DbContext would be kept alive during the whole application lifetime.
Please let me know how you go!

OWIN Service resolution Using Autofac

I have an WebApi application using OWIN and Autofac. Although controllers and parameters get resolved correctly, I would like to be able to use OwinContext.Get<type> to resolve types registered with Autofac. Is that posible?
Already setapp.UseAutofacMiddleware(container); and config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
By example, I registered builder.Register<IAppConfiguration>(c => new AppConfig()); and I'd like to resolve it using owinContext.Get<IAppConfiguration>().
There is no way to get OwinContext.Get<T> to resolve things from Autofac. If you dive into Microsoft.Owin.OwinContext.Get in Reflector, you'll see it's backed entirely by a dictionary of things you register with an environment. It's not dynamic and there's no way (without creating your own IOwinContext implementation) to get it to resolve things either out of the dictionary or out of dependency resolution.
If you are in a DelegatingHandler or an ApiController you will have a reference to the current HttpRequestMessage. Use message.GetDependencyScope() to get the current request-level dependency scope to resolve services.
public HttpResponseMessage SomeControllerAction()
{
var service = this.Request.GetDependencyScope().GetService(typeof(Service));
}
If you have access to the HttpConfiguration then you can use the HttpConfiguration.DependencyResolver to resolve things. Note that resolver will not have per-request dependencies available. Web API tracks request dependency scope with the inbound HttpRequestMessage so be aware of that limitation. There is an FAQ about per-request lifetime scope that can help you through that.
If you're in a place where there's only an IOwinContext, you may need to make use of a package like CommonServiceLocator and the associated Autofac.Extras.CommonServiceLocator. There really isn't a way to get a reference to the current HttpConfiguration or global container just from an IOwinContext. Again, if you go this route, you won't have per-request dependencies available, so be aware.
The IOwinContext.Get uses the Environment dictionary, resolving objects registered directly with Owin, it does not take into account Autofac container.
I managed to do it by accessing the Autofac OwinLifetimeScope in the Environment property and using the scope to resolve the service.
You can access the LifetimeScope using this code
var scope=OwinContext.Get<Autofac.Core.Lifetime.LifetimeScope>("autofac:OwinLifetimeScope");
and then
scope.GetService(type)
You should check for nulls and write it in a better way, as Extension method maybe.
If you have WebAPI in your project, you can simulate a http request like this
var dependencyScope = new AutofacWebApiDependencyScope(owinContext.GetAutofacLifetimeScope());
var myService = dependencyScope.GetService(typeof(MyService));

Supply user specific dependencies to MVC controller with Ninject

I have some controllers that require a web service connection (an instance of MS Dynamics CRM CrmService) and I would like the controllers to receive this through their constructors. The CRM service has to be set up with a token that is based on who the currently logged in user is (when the user logs in the application authenticates against the CRM and can store the returned token in Session).
I'm not sure how best to supply this instance using Dependency Injection and Ninject. It seems a bit rubbish for the Ninject ToMethod() Func<> to access FormsAuth/Session for the current request (to obtain the token if authenticated) to create the appropriate instance. I'm also not sure what should happen if the user is not authenticated - I don't need these users be able to access the controller but the controller will be instantiated before any filters like [Authorize] will run so the dependency will always have to be met. From what I have read returning null is not ideal and I would have to change the Ninject configuration to do this anyway.
I was thinking that maybe the controller could get an instance of ICrmServiceFactory or something but that doesn't help me if the controllers end up having other dependencies which also rely on CrmService directly (and don't want to be passed a factory).
Any advice on how to solve this would be appreciated.
I usually set up a binding for IPrincipal:
kernel.Bind<IPrincipal>().ToMethod(c => HttpContext.Current.User);
Never really had a problem with this approach.
If I understand your question correctly then your controller has a dependency to CrmService and the CrmService requires some token stored in the session.
In that case you could inject a CrmTokenProvider to CrmService and add a property to that class which gets the value from the session whenever it is requested by the CrmService.
public class CrmService
{
public CrmService(CrmTokenProvider tokenProvider)
{
this.tokenProvider = tokenProvider;
}
public void DoSomeWork()
{
...
this.tokenProvider.Token;
...
}
}
I have ended up implementing this as follows:
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<CrmService>()
.ToMethod(context =>
{
//return unauthenticated instance if user not logged in.
if (!HttpContext.Current.User.Identity.IsAuthenticated) return new CrmService();
return GetConnection(HttpContext.Current);
})
.InRequestScope();
}
private static CrmService GetConnection(HttpContext ctx)
{
//get stuff out of session and return service
}

Is there any benefit to using single Repository instance for Asp.net Mvc application?

In CarTrackr project, It use some technique that creates only 1 repository instance for all request in Asp.net Mvc website and uses UnityControllerFactory class to manage all repository instanes(send to requested controller).
Is there any benefit to using single repository instance when compare with creating new repository instance every request?
I know, it may improve overall performance. But, Does it cause any transcation problem?
partial Global.asax
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
RegisterRoutes(RouteTable.Routes);
RegisterDependencies();
}
protected static void RegisterDependencies() {
IUnityContainer container = new UnityContainer();
// Registrations
container.RegisterType<IUserRepository, UserRepository>(new ContextLifetimeManager<IUserRepository>());
container.RegisterType<ICarRepository, CarRepository>(new ContextLifetimeManager<ICarRepository>());
// Set controller factory
ControllerBuilder.Current.SetControllerFactory(
new UnityControllerFactory(container)
);
}
}
partial CarController.cs
[Authorize]
public class CarController : Controller
{
private IUserRepository UserRepository;
private ICarRepository CarRepository;
public CarController(IUserRepository userRepository, ICarRepository carRepository)
{
UserRepository = userRepository;
CarRepository = carRepository;
}
}
Thanks,
Creating a repository instance per request by itself shouldn't cause any performance issue; the repository is often pretty shallow, and when it needs to access data things like connection pooling minimise the cost of establishing actual connections. Object creation is astonishingly cheap, especially for short-lived things like web requests where the object gets collected while still in "generation zero".
As to whether to have a single repository or a repository per instance - that depends on the repository ;-p
The biggest question is: is your repository thread safe? If not: one per request.
Even if it is though; if your repository itself keeps something like a LINQ-to-SQL DataContext (that you synchronize somehow), then you have big problems if you keep this long-term, in particular with the identity manager. You'll quickly use a lot of memory and get stale results. Far form ideal.
With a single repository instance, you will probably also end up with a lot of blocking trying to get thread safety. This can reduce throughput. Conversely, the database itself has good ways of achieving granular locks - which is particularly useful when you consider that often, concurrent requests will be looking at separate tables etc - so no blocking at the database layer. This would be very hard to do just at the repository layer - so you'd probably have to synchronize the entire "fetch" - very bad.
IMO, one per request is fine in most cases. If you want to cache data, do it separately - i.e. not directly on the repository instance.
I think you're misunderstanding whats happening with the ContextLifeTimeManager. By passing the manager into the Register() method your telling Unity to set the caching scope for your repository instance to HttpContext.
It is actually incorrect to say:
It use some technique that creates only 1 repository instance for all request in Asp.net > Mvc website
There is not a repository singleton. Unity is creating one for each request. It sounds like this is actually your desired behavior.
When the manager's scope is set to HttpContext the container looks to HttpContext for an existing instance of the requested type (in this case, your repository). Since the HttpContext is fresh on each request, the container will not have this instance, thus a new one will be created.
When you ask:
Is there any benefit to using single
repository instance when compare with
creating new repository instance every
request?
No.
As far as transaction problems: Threading will def be an issue. The CarRepository appears to be using Linq2Sql or Linq2Entities. Its ctor requires an active datacontext. DataContext is NOT thread safe. If the datacontext is being stored at a scope higher than the current request, there will be problems.
Using the new ContextLifetimeManager());, the lifetime of a repository is limited to one request. This means that evry request each repository is instantiated (if needed) and destroyed once a response has been sent to the client.

Resources