access appsetting from data layer without creating instantiation with parameter - c#

How can i access my "appsettings.js" values in Business/Data layer without creating instantiation in the constructor level.
I can access all values in the controller but i don't want to send to all my layers like passing constructor parameter.
I am trying to understand this post but i don't understand fully. can some one provide me some sample code with out creating instantiation
ASP.NET 5 DI app setting outside controller
Controller - Services - DBServices (without parameter constructor?)
appsetting.json
"DbSettings":{
"ConnectionString" : "TESTING Connection string here"
}
Controller:
public class TestController : ControllerBase
{
public TestController(IOptions<DbSettings> dbSettings)
{
_balService = new BALServices(dbSettings.Value); // passing parameter "dbsetting" to constructor which i don't want.
}
}
Startup.cs
services.Configure<DbSettings>(Configuration.GetSection("DbSettings"));
services.AddSingleton<IConfiguration>(Configuration);
Dbsettings.cs
public class DbSettings
{
public string ConnectionString { get; set; }
}

The framework isn’t really designed to allow you to do that. ASP.NET Core uses dependency injection and kind of forces you to follow it, since pretty much everything is inaccessible outside of the DI container. So whenever something depends on something, then it should make that dependency clear by expecting it in the constructor. That is the way it is designed.
That being said, you creating a new instance of BALServices isn’t really in the spirit of dependency injection either. If you want to use BALServices in the controller, then instead of creating an instance of it itself, the controller should just depend on that type.
So you would change the controller to look like this:
public class TestController : ControllerBase
{
private readonly BALServices _balService;
public TestController(BALServices balService)
{
_balService = balService;
}
}
Now, the controller does not need to worry about how it could possibly create that object. It just depends on it being there and letting someone else figure that out. And that’s exactly what dependency injection is about.
In order to make that work, of course you now need to adjust your BALServices to depend on those IOptions<DbSettings> instead:
public class BALServices
{
private readonly DbSettings _dbSettings;
public BALServices(IOptions<DbSettings> dbSettings)
{
_dbSettings = dbSettings.Value;
}
}
And then you only need to register this service in your Startup:
services.AddScoped<BALServices>();
And now you have TestController depend on the actual service it wants to use, and BALServices depend on the configuration it requires. And the DI container will automatically provide you with what you need.

Related

Which layer should read from the application configuration in an N-Tier application?

While working on several projects based on an N-Tier architecture I often noticed that I am not quite sure where to actually read from the configuration.
For example, let's say I have a project with an application layer, a business layer and a data layer. The business layer contains a function PerformImport() which performs a data import from a data source. The first step of this import is logging in to get access to the data from the data source. To do this, the function calls a function Login() which is implemented in the data layer. Should it:
Read the login username and password from the configuration and pass it to the Login() function or
Call the Login() function without parameters and have the credentials read in the function itself?
I can't really think about any reasons for or against the first or the second solution, so I am often not sure what to do here. This same question applies to many other possible situations, such as time intervals, URLs, database names or really anything that could be possibly stored in a configuration.
I was also thinking about reading it in the application layer and then passing it down to wherever the configuration entry is needed, but this would often result in a big list of parameters in the lower layers and just does not seem very efficient at all.
My answer will assume that you are using Dependency Injection.
My usual method to deal with this, is to define a Settings class next to the Implementation class. Register this Settings class in the DI container, and inject it in the Implementation class.
An example.
Lets assume we have a service which is defined by this interface.
public interface IMyService
{
// snip for brevity
}
And we have the implementation of it somewhere.
public class MyService : IMyService
{
// snip for brevity
}
Lets say that the service needs some settings. So define the settings class.
public class MyServiceSettings
{
public string UserName { get; set; }
public string Password { get; set; }
public int TimeOutInSeconds { get; set; }
}
Lets inject this Settings class into the Implementation.
public class MyService : IMyService
{
public MyService(MyServiceSettings settings)
{
this.settings = settings;
}
private readonly MySettings settings;
// snip for brevity
}
Now we can use the settings in the implementation whenever we want.
Now we need to register the Settings class in the DI container. Lets assume we have a container, and the IMyService is already registered. Now add the Settings class there.
public void CreateContainer()
{
var container = new Container();
container.RegisterScoped<IMyService, MyService>();
var myServiceSettings = new MyServiceSettings();
// TODO: Set values from configuration file, or a keyvault, or Azure Devops Variables, etc
container.RegisterInstance(myServiceSettings);
}
Now you have all the parts needed to use the settings wherever you need them.
Now where you store the settings, is IMHO usually tied to the resulting build, e.g. an executable. I do not want my class libraries to retrieve the settings from a database or configuration file, they only consume the settings instances I give them.
This technique is really easy to implement if you use the ASP.NET Core Configuration abstractions as described here: https://learn.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-6.0

.Net core Dependency injection - with parameters

NOTE: This example has been simplified
I have got a Client's Contact table and wanted to retrieve specific client contact information from DB. The code I typed belove brings me all contact details. I wanted to use a parameter to only bring me specific client contacts.
I used IClientContactRepository interface like this
public interface IClientContactRepository
{
IQueryable<ClientContactModel> ClientContacts { get; }
}
And i used this class to retrive data from database with dapper
public class ClientContactRepository : IClientContactRepository
{
private readonly IConfiguration configuration;
private List<ClientContactModel> ClientContactList {get;set;}
public ClientContactRepository(IConfiguration config)
{
configuration = config;
SqlConnection conn = new SqlConnection(configuration["ConnectionString"]);
using (var connection = conn)
{
ClientContactList = connection.Query<ClientContactModel>("Select * FROM ContactTable ").ToList();
}
}
public IQueryable<ClientContactModel> ClientContacts => ClientContactList;
}
In my Startup class
services.AddTransient<IClientContactRepository, ClientContactRepository>();
My QUESTION is: can I pass the client's id parameter to the constructor.
I tried this: add a parameter to the constructor
public ClientContactRepository(IConfiguration config, int clientId)
and tried to start up class.
services.AddTransient<IClientContactRepository, ClientContactRepository(int,i)>()
Didn't work....
Can someone help me how to pass parameter please?
Yes, but where are you getting the client ID from - is it a configured value that will be static for the lifetime of the application? If so, you can use the AddTansient method overload that accepts a factory delegate to create the objects.
The better way (will cover all use cases) is registering the type that can provide that information (create one if no such type exists) with the DI container and use that as a parameter in the constructor of your repo.
As an example, let’s say you get your client ID from a claim, so the type you need to inject is IPrincipal:
services.AddScoped<IPrincipal>(
provider => provider.GetService<IHttpContextAccessor>()
.HttpContext
.User);
You would then inject the IPrincipal into your repo constructor and retrieve the client ID. An even better way would be to create your own type “ClientIdAccessor” which is responsible for providing the client ID. You would then not have a dependency on IPrincipal when testing your repo and the implementation of this new type would only depend on external libraries for your asp.net core implementation.
Side note: are you certain you want to use AddTransient for your repo? Usually you’d want to use the same repo object for the lifetime of the request (I.e. AddScoped).

Is it possible to inject a specific configuration class bound as a suboption and not to IConfiguration<MyType>?

I have a class that I want injected into some controllers. It has a few dependencies that I want to be automatically injected. Specifically this class requires a configuration object be passed in.
So my appsettings.json file looks something like this:
{
"MyType": {
"Option1": "value"
}
}
And I have a class that mirrors this, ex.
public class MyTypeConfig
{
public string Option1 { get; set; }
}
I have registered this in my startup class.
services.Configure<MyTypeConfig>(Configuration.GetSection("MyType"));
However, I want to receive a "naked" version of MyTypeConfig in the class being instantiated, NOT IConfigureOptions<MyTypeConfig> which is what the DI system seems to want to inject.
The constructor for the class being injected looks liked this (which works):
public MySampleClass(IHttpClientFactory httpClient, IConfigureOptions<MyTypeConfig> configuration, ILogger<MySampleClass> logger)
However, this is really want I want:
public MySampleClass(IHttpClientFactory httpClient, MyTypeConfig configuration, ILogger<MySampleClass> logger)
I've looked through the topic on the Microsoft site, here:
https://learn.microsoft.com/en-us/aspnet/core/fundamentals/configuration/options?view=aspnetcore-2.2
But I'm not really finding an answer.
How can I just inject the MyTypeConfig?
Get the class from configuration during startup and register it with the service collection.
MyTypeConfig config = Configuration.GetSection("MyType").Get<MyTypeConfig>();
services.AddSingleton<MyTypeConfig>(config);
Reference Configuration in ASP.NET Core : Bind to an object graph
In 2022, imho, there is a better way to do that
Reference

How do I get access to INodeServices without dependency injection

I'd like to run some node code from my c#. Microsoft.AspNetCore.NodeServices seems to be the way to do this job however the examples are all very similar and all involve putting
services.AddNodeServices();
in the configure services function and then DI adds the implementation of INodeServices to a controller. Like this
public class foo
{
private readonly INodeServices _nodeServices;
public foo(INodeServices nodeServices)
{
_nodeServices = nodeServices;
}
}
As I'm using this in a class library rather than a webapi how is DI going to work? Also how do I call the class from a unit test, what can I pass into the constructor? I'm sure I'm missing something obvious.
The concept of DI is that it can be used to resolve object graphs. That is, it doesn't just resolve dependencies of the Controller class, but dependencies of those dependencies, dependencies of those dependencies, etc.
To use INodeServices in your own library, you simply need to reference Microsoft.AspNetCore.NodeServices, then accept it as a constructor parameter.
public class MyServiceFromMyLibrary : IMyServiceFromMyLibrary
{
private readonly INodeServices nodeServices;
public MyServiceFromMyLibrary(INodeServices nodeServices)
{
this.nodeServices = nodeServices;
}
// ...
}
Then reference your library from the Web API project and inject your service into a controller.
public class FooController
{
private readonly IMyServiceFromMyLibrary myService;
public FooController(IMyServiceFromMyLibrary myService)
{
this.myService = myService;
}
}
DI takes care of putting the INodeServices instance into your class provided it is registered in your composition root, as follows.
services.AddNodeServices();
services.AddTransient<IMyServiceFromMyLibrary, MyServiceFromMyLibrary>();
If your end game is to create a reusable library rather than an application layer refer to DI Friendly Library for some techniques to make your library easier to use without the use of dependency injection.
Also how do I call the class from a unit test, what can I pass into the constructor?
For a unit test, you would just need to mock INodeServices. The simplest way is to use a mocking library, such as Moq.
var mock = new Mock<INodeServices>();
mock.Setup(ns => ns.InvokeAsync(It.IsAny<string>())).Returns(...);
var target = new MyServiceFromMyLibrary(mock.Object);
// .. Call a method on target and then assert the results
References:
Using Node Services in ASP.NET Core
Dependency injection in ASP.NET Core

Injecting runtime value into Unity dependency resolver

I am working on a webapi project and using Unity as our IOC container. I have a set of layered dependencies something like the following:
unityContainer.RegisterType<BaseProvider, CaseProvider>(new HierarchicalLifetimeManager());
unityContainer.RegisterType<IRulesEngine, RulesEngine>();
unityContainer.RegisterType<IQuestionController, QuestionController>();
unityContainer.RegisterType<IAPIThing, WebAPIThing>();
Now the constructor for BaseProvider accepts an int as a parameter which is the Case identifier. WebAPIThing takes a BaseProvider in its constructor. Normally in a non web scenario I would inject the case id using something like:
public static IAPIThing GetIAPIThing(int caseId)
{
return CreateUnityContainer().Resolve<IAPIThing >(new ParameterOverride("caseId", caseId).OnType<CaseProvider>());
}
But that only works when I explicitly call that method. In a Web API scenario I am using a
config.DependencyResolver = new UnityDependencyResolver(unityContainer); to resolve my api controllers.
I would guess I will still need to influence how the DependencyResolver resolves that BaseProvider object at runtime.
Anyone had to do something similar?
EDIT 1
I have tried using the following which appears to work:
unityContainer.RegisterType<BaseProvider>(
new HierarchicalLifetimeManager()
, new InjectionFactory(x =>
new CaseProvider(SessionManager.GetCaseID())));
You are trying to inject a runtime value (the case id) into the object graph, which means you are complicating configuration, building, and verification of the object graph.
What you should do is promote that primitive value to its own abstraction. This might sound silly at first, but such abstraction will do a much better job in describing its functionality. In your case for instance, the abstraction should probably be named ICaseContext:
public interface ICaseContext
{
int CurrentCaseId { get; }
}
By hiding the int behind this abstraction we effectively:
Made the role of this int very explicit.
Removed any redundancy with any other values of type int that your application might need.
Delayed the resolving of this int till after the object graph has been built.
You can define this ICaseContext in a core layer of your application and everybody can depend on it. In your Web API project you can define a Web API-specific implementation of this ICaseContext abstraction. For instance:
public class WebApiCaseContext : ICaseContext
{
public int CurrentCaseId
{
get { return (int)HttpContext.Current.Session["CaseId"];
}
}
This implementation can be registered as follows:
unityContainer.RegisterType<ICaseContext, WebApiCaseContext>();
UPDATE
Do note that your own new CaseProvider(SessionManager.GetCaseID()) configuration does not solve all problems, because this means that there must be a session available when verifying the object graph, which will neither be the case during application startup and inside a unit/integration test.

Categories

Resources