I need to get a scoped service injected into an IOperationFilter but it won't work by c-tor:
class MyOperationFilter: IOperationFilter
{
public MyOperationFilter(IMyService service) { }
}
it will give an error:
System.InvalidOperationException: 'Cannot resolve scoped service from root provider site:
this is expected because only a transient service can get injected, not a scoped one.
So how can I get a scoped service injected in an IOperationFilter?
There's no example in the documentation or anywhere else. The examples I've seen use transient not scoped services.
In ASP.NET Core, a scoped service can get injected into the middleware by adding the service as parameter to the Invoke method. But Swashbuckle doesn't seem to have an extension to allow this.
Looking at the source code, I cannot see Swashbuckle to have a way to do this.
You can go with two methods:
Inject IHttpContextAccessor if we are talking about scoped service for user request, and then request the scoped service to request.
_httpContextAccessor.HttpContext.RequestServices.GetRequiredService<ICurrentIdentity>();
2.Inject IServiceProvider and create a new scope, and then request your scoped service, but it will not have references to the current request.
serviceProvider.CreateScope().ServiceProvider.GetService<MyScopedService>()
Related
I want to be able to reload my Swagger configuration without redeploying my service.
So I'm trying to use an IOptionsSnapshot directly in the Startup.ConfigureServices() method :
public void ConfigureServices(IServiceCollection services)
{
services.Configure<SwaggerSettings>(Configuration.GetSection("BaseTemplate:Swagger"));
var swaggerSettings = new IOptionsSnapshot<SwaggerSettings>(); //get an instance
//Configure Swagger
}
I guess that the Startup.ConfigureServices() is called only once when the application is starting ?
Is there any workaround to use and reload a IOptionsSnapshot in the the Startup.ConfigureServices() ?
Yes, the Startup.ConfigureServices() is called only once when the application is starting.
Is there any workaround to use and reload a IOptionsSnapshot in the
the Startup.ConfigureServices() ?
Do you mean you want to create the service instance each time they're requested from the service container or once per client request (connection)? If that is the case, you could try to use AddTransient method or AddScoped method to register the service. Code like this:
services.AddScoped<IMyDependency, MyDependency>();
More detailed information, see:
Transient
Transient lifetime services are created each time they're requested from the service container. This lifetime works best for lightweight, stateless services. Register transient services with AddTransient.
In apps that process requests, transient services are disposed at the end of the request.
Scoped
For web applications, a scoped lifetime indicates that services are created once per client request (connection). Register scoped services with AddScoped.
In apps that process requests, scoped services are disposed at the end of the request.
Reference: Dependency injection in ASP.NET Core and Service lifetimes.
I need to create a service class for my constructor in which I need to load a lot of configurations from my appsettings.json.
I want this service to be created as singleton and need to load configurations values in the service itself. So please anyone suggest me the best way to do so. I am creating asp.net core webapi and using its core DI built in container.
The configuration is already pre-registered by the host that is used with ASP.NET Core. So you can just register your service as you would any other singleton service, and have it depend on the configuration by requiring IConfiguration in the constructor:
public class MyService
{
private readonly IConfiguration _config;
public MyService(IConfiguration config)
{
_config = config;
}
}
You can then register this service as a singleton directly in your ConfigureService method:
services.AddSingleton<MyService>();
Things that now depend on your service, for example constructors, will automatically get a reference to that service instance. And since it is registered as singleton, it will only be created once by the DI container.
If you want a bit more control over your configuration, then I would suggest you to adapt the options pattern to make sure that you can work with strongly typed configuration and to avoid unrelated configuration value from spilling into services that shouldn’t not have access to them.
I am usually working with WCF services that uses single instance context mode. Also service contract and behavior is in a WCF service Library.
If the service is hosted as a Windows Service or a Web service, they get their own projects that references the WCF service library. I like to keep this WCF service library running (for simply debugging with WCF Test Client) but it requires too much effort when I try to resolve dependencies through the behavior class.
Using Castle Windsor, I also have to make additional configuration for Castle Windsor WCF Integration Facility. I am just trying to resolve the object graph on service startup and I feel like it shouldn't be this hard.
I thought, since behavior instance is created only once I should be able to use it as the composition root. I can provide all dependencies using a single object and resolve it from the container like this:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class SampleService : ISampleService, IDisposable
{
private readonly IServiceManager _serviceManager;
private readonly IWindsorContainer _container;
public SampleService()
{
_container = new WindsorContainer();
_container.Install(new ServiceInstaller());
_serviceManager = _container.Resolve<IServiceManager>();
}
public string GetMessage()
{
return _serviceManager.GetMessage();
}
public void Dispose()
{
_container.Dispose();
}
}
I know it's a bad idea to explicitly ask the container to resolve a dependency but this saves me from so much trouble. I get to keep the default WCF configuration, I can run the WCF service library for debugging since I have a default constructor now. I also don't have to use Castle Windsor WCF integration Facility which was missing documentation last time I checked.
I guess Castle Windsor WCF integration Facility offers more features but I just want to resolve the dependencies. Is this approach likely to cause some problems? I haven't seen anyone do it like this so I would like to know if this would be legitimate use.
I have a WCF service which implemented using Repository and UnitofWork patterns.
And now I am getting following error:
The service type provided could not be loaded as a service because it does not have a default (parameter-less) constructor. To fix the problem, add a default constructor to the type, or pass an instance of the type to the host.
When I worked WIHTOUT these patterns it did not throw any error.
HELP ?? SUGGESTIONS? How to get passed this error?
Following is the code snippet:
public class Service : IService
{
private IUnitOfWork _unitOfWork;
private IMyRepository _myRepository;
// Dependency Injection enabled constructors
public Service(IUnitOfWork uow, IMyRepository myRepository)
{
_unitOfWork = uow;
_myRepository = myRepository;
}
}
If you use default service instancing you must provide parameterless constructor. Your design provides dependency injection through constructor. In such case you must have your own instance provider to call the constructor and create service instance. You can create per service instance provider, behavior and optionally service host but it is really bad way. The better way is to use Inversion of Control container which will resolve your dependencies from configuration. In that case you will have only one new instance provider, behavior and optionally service host.
Here you have very nice post about creating new instnace provider which resolve services through Unity.
I have run into an issue while creating a data service and using Autofac WCF Integration to resolve a dependency on my data model. Registrations are of the form:
builder.RegisterType<MyService>()
.InstancePerDependency();
builder.RegisterType<MyModel>()
.InstancePerLifetimeScope();
where MyModel has a dependency on MyProvider
public MyModel (MyProvider provider)
{
_provider = provider;
}
The problem arises as this provider is registered in Request scope for reasons pertinent to my application.
builder.RegisterType<MyProvider>()
.As<MyProvider>()
.InstancePerMatchingLifetimeScope(RequestContextTag);
As might be obvious, request container is created and disposed on each ASP.Net request.
However, MyModel and MyService are registered in Application scope. I came up with two possible solutions -
Change scope of provider (not possible as will have to remodel almost the entire app)
Register service and model in request scope (Don't know if this is possible and if at all, correct)
Any advice/ suggestions appreciated. Thanks.
I guess by your statement "registered in Request scope" that you mean the ASP.NET "request" scope as configured via ContainerProvider? (If not please clarify.)
The request lifetime is only seen by ASP.NET requests, and not WCF requests - WCF uses a different pipeline.
There is probably a way to achieve what you want so please post some details of the MyProvider registration.
Make sure your per-request component doesn't depend on any of the ASP.NET "Http" types, which will not be available during a WCF request regardless of whether Autofac is used or not.
Hope this helps!
Nick