How to configure Dependency Injection in my own class - c#

I wish to use settings from appsettings.json in my own class.
I have this working well in a controller and in razor. I tried to use the same code as in a controller in my own class:
public class Email
{
private readonly IConfiguration _config;
public Email(IConfiguration config)
{
_config = config;
}
but when I try to call this
Email sendEmail = new Email();
it requires that I provide config as a parameter. Shouldn't the DI system provide (inject) this? In ConfigureServices I have this:
services.AddSingleton(Configuration);
Do I need to register Email class somewhere too? Do I need to call it some different way?

When you use the following code:
Email sendEmail = new Email();
The DI system isn't involved at all - You've taken things into your own hands. Instead, you should add Email to the DI system and then have it injected. e.g.:
services.AddSingleton<Email>(); // You might prefer AddScoped, here, for example.
Then, as an example, if you're accessing Email in a controller, you can have it injected too:
public class SomeController : Controller
{
private readonly Email _email;
public SomeController(Email email)
{
_email = email;
}
public IActionResult SomeAction()
{
// Use _email here.
...
}
}
Essentially, this just means you need to use DI all the way. If you want to provide more details about where you're currently creating your Email class, I can tailor the examples more to that.
It's a bit of an side, but you can also inject dependencies using the [FromServices] attribute inside of an action. Using this means you can skip the constructor and private field approach. e.g.:
public class SomeController : Controller
{
public IActionResult SomeAction([FromServices] Email email)
{
// Use email here.
...
}
}

As you mentioned, you defined a constructor which requires the parameter.
Please check out the concept of Class Constructors.
Injection is design pattern, when we use class and interfaces to implement it, it should still follow the basic Class methodology and concept.
Hope it helps.

Related

Dotnet core method injection with controller methods

Lets say i have the following controller in dotnet core:
[Route("api/v1/[controller]")]
public class ValuesController : Controller
{
private readonly IHandler<ValuesRequest, ValuesResponse> _valueHandler;
private readonly IHandler<ValuesIdRequest, ValuesIdResponse> _valueIdHandler;
public ValuesController(IHandler<ValuesRequest, ValuesResponse> valueHandler,
IHandler<ValuesIdRequest, ValuesIdResponse> valueIdHandler)
{
_valueHandler = valueHandler;
_valueIdHandler = valueIdHandler;
}
[HttpGet]
public ValuesResponse Get(ValuesRequest request)
{
return _valueHandler.Handle(request);
}
[HttpGet("{id}")]
public ValuesIdResponse Get(ValuesIdRequest request)
{
return _valueIdHandler.Handle(request);
}
}
As you can see in the code above, I'm using dependency injection though the constructor. However, I was thinking on how I could reduce the amount of code. So, I was thinking about using method injection, which should reduce the code to something like this:
[Route("api/v1/[controller]")]
public class ValuesController : Controller
{
[HttpGet]
public ValuesResponse Get(ValuesRequest request, IHandler<ValuesRequest, ValuesResponse> handler)
{
return handler.Handle(request);
}
[HttpGet("{id}")]
public ValuesIdResponse Get(ValuesIdRequest request, IHandler<ValuesIdRequest, ValuesIdResponse> handler)
{
return handler.Handle(request);
}
}
I was wondering if it is possible to do something like this in combination with controller params. I tried finding an answer on the web, however I could not find similar problem/solution.
Reference Action Injection with FromServices
Sometimes you don't need a service for more than one action within your controller. In this case, it may make sense to inject the service as a parameter to the action method. This is done by marking the parameter with the attribute [FromServices] as shown here:
public ValuesResponse Get(ValuesRequest request, [FromServices]IHandler<ValuesRequest, ValuesResponse> handler)
{
return handler.Handle(request);
}
While the answer would work using [FromService] within your actions, I have another suggestion.
From what I understand by reading the code you have provided is, that you use some kind of CQRS. For that case I can suggest MediatR. You will then only need to inject one interface into your controller and send your request using the IMediator. This way you will keep your controller small and clean and you will not need to inject all the other handlers.
There is a nice and handy extension for Microsoft's IoC-Container to register all your handlers and all other necessary classes to use MediatR.
services.AddMediatR(typeof(Startup).Assembly);

How to inject User Identity in Asp.Net web api controller constructor?

I have a controller decorated with [Authorize] attribute. I would like to accomplish the following so that I don't have to repeatedly create repository obj and pass currentUser in each method:
[Authorize]
public class HomeController : ApiController
{
Repository repo;
public HomeController()
{
var userName = User.Identity.IsAuthenticated ? User.Identity.Name : null;
repo = new Repository(userName);
}
}
I know User.Identity is not available in constructor or in Initialize method.
What is the best practice to inject authenticated user in controller constructor.
If we use dependency injection - while registering our custom created UserResolverService inside WebApiConfig.cs in Register method - User.Identity is not available at this point as well.
This is a very common issue with web api but somehow couldn't find any article showing proper solution.
Is it really achievable and if yes - can you please provide some sample code?
Here is how I worked around this (not sure how appropriate this method is, but it works).
In your BaseContoller (a controller from which all other controllers inherit from) create instance of Repository like so:
private Repository _Repository;
private Repository Repository
{
get
{
_Repository.InjectUsername(User.Identity.Name); // value is already available here
return _Repository;
}
set
{
_Repository = new Repository();
}
}
Notice how your Repository has InjectUsername method. That method will simple assign passed parameter to some Repository's property, like so:
public class Repository
{
private string Username { get; set; }
public void InjectUsername(string username)
{
Username = username;
}
}
Every time you will call some method in repository from a controller action you will inject usrename which will already exist, and you won't have to duplicate code by passing username to every method in repository every time you call it.
You can register a factory delegate and get user identity from HttpContext.Current.
Here's a sample code for simpleinjector
container.Register<IPrincipal>(() => HttpContext.Current.User);

How to register Drum.UriMaker<> using Simple Injector?

I'm using Drum which provides a generic class `UriMaker:
public class UriMaker<TController>
{
// I need use this one
public UriMaker(UriMakerContext context, HttpRequestMessage request) { }
public UriMaker(Func<MethodInfo, RouteEntry> mapper, UrlHelper urlHelper) { }
}
Used like this:
public class UserController : ApiController
{
public UserController(UriMaker<UserController> urlMaker) {}
}
I've used to register it with Unity:
container.RegisterType(typeof(UriMaker<>),
new InjectionConstructor(typeof(UriMakerContext), typeof(HttpRequestMessage)));
but now migrating to Simple Injector. I already have this:
UriMakerContext uriMaker = config.MapHttpAttributeRoutesAndUseUriMaker();
container.RegisterSingle(uriMakerContext);
So how now register UriMaker<> itself?
Although it is possible to configure Simple Injector to allow injecting an UriMaker<TController> directly into your controllers, I strongly advice against this for multiple reasons.
First of all, you should strive to minimize the dependencies your application takes on external libraries. This can easily be done by defining an application specific abstraction (conforming the ISP).
Second, injecting the UriMaker directly makes your extremely hard to test, since the UriMaker is pulled into your test code, while it assumes an active HTTP request and assumes the Web API route system to be configured correctly. These are all things you don't want your test code to be dependent upon.
Last, it makes verifying the object graph harder, since the UriMaker depends on an HttpRequestMessage, which is a runtime value. In general, runtime values should not be injected into the constructors of your services. You should build up your object graph with components (the stuff that contains the application's behavior) and you send runtime data through the object graph after construction.
So instead, I suggest the following abstraction:
public interface IUrlProvider
{
Uri UriFor<TController>(Expression<Action<TController>> action);
}
Now your controllers can depend on this IUrlProvider instead of depending on an external library:
public class UserController : ApiController
{
private readonly IUrlProvider urlProvider;
public UserController(IUrlProvider urlProvider)
{
this.urlProvider = urlProvider;
}
public string Get()
{
this.urlProvider.UriFor<HomeController>(c => c.SomeFancyAction());
}
}
Under the covers you of course still need to call Drum, and for this you need to define a proxy implementation for IUrlProvider:
public class DrumUrlProvider : IUrlProvider
{
private readonly UriMakerContext context;
private readonly Func<HttpRequestMessage> messageProvider;
public DrumUrlProvider(UriMakerContext context,
Func<HttpRequestMessage> messageProvider)
{
this.context = context;
this.messageProvider= messageProvider;
}
public Uri UriFor<TController>(Expression<Action<TController>> action)
{
HttpRequestMessage message = this.messageProvider.Invoke();
var maker = new UriMaker<TController>(this.context, message);
return maker.UriFor(action);
}
}
This implementation can be registered as singleton in the following way:
container.EnableHttpRequestMessageTracking(config);
UriMakerContext uriMakerContext =
config.MapHttpAttributeRoutesAndUseUriMaker();
IUrlProvider drumProvider = new DrumUrlProvider(uriMakerContext,
() => container.GetCurrentHttpRequestMessage());
container.RegisterSingle<IUrlProvider>(drumProvider);
This example uses the Simple Injector Web API integration package to allow retrieving the current request's HttpRequestMessage using the EnableHttpRequestMessageTracking and GetCurrentHttpRequestMessage extension methods as explained here.

mvc5: Cannot access a disposed object. asp.net mvc5 using unity

im using vs 2013, mvc5 and ef6 + unity.mvc5:
my account controller class has this constructor:
public AccountController(UserManager<ApplicationUser> userManager)
{
this.UserManager = userManager;
}
and this is my unity config:
container.RegisterType(typeof(AccountController),
new InjectionConstructor(new UserManager<ApplicationUser>(new UserStore<ApplicationUser>())));
when i try to register a new user i get this exception:
Cannot access a disposed object.
Object name: 'UserManager`1'.
on this line of code and register action:
var result = await UserManager.CreateAsync(user, model.Password);
when i remove unity and set dependecy resolver to default it works just fine.
i`v tried many unity configs but didnt work...
thanks alot for reading.
i found the solution, changed the unity config to this:
container.RegisterType<IUserStore<ApplicationUser>,
UserStore<ApplicationUser>>(new InjectionConstructor(new ApplicationDbContext()));
thanks all.
Do NOT create a parameterless constructor, (I can't vote it down as I don't have enough reputation), that answer totally avoids IoC and instead tries to build up the object by knowing the entire dependency hierarchy for the object, i.e. AccountController needs to know that it has a dependency on UserStore and it needs to know that Userstore has a dependency on UserContext. This is exactly what DI containers are there to avoid!
It is hard to provide you with an exact answer as there is a lot of your code missing.
One thing that looks odd to me is that you have an uppercase UserManger, that usually means that you are using it as a type, not referencing a local private variable. Can you show me the rest of the code?
Also, I would question why you are not referencing everything via Interfaces. That is by far the preferred way to set up proper DI.
I will try to knock up some test code that shows what I would do and then post this here, if you could answer those questions in the meantime that would be great.
Cheers Mike
Here is what I would do.
In your controller
public class HomeController : Controller
{
private IUserManager<ApplicationUser> userManager;
public HomeController(IUserManager<ApplicationUser> userManager)
{
this.userManager = userManager;
}
public ActionResult Index()
{
var user = "user";
var password = "password";
var result = userManager.CreateAsync(user, password);
return View();
}
}
Interface for UserManager
public interface IUserManager<T> where T : ApplicationUser
{
int CreateAsync(string user, string password);
}
Actual UserManager class
public class UserManager<T> : IUserManager<T> where T : ApplicationUser
{
private IUserStore<ApplicationUser> userStore;
public UserManager(IUserStore<ApplicationUser> userStore)
{
this.userStore = userStore;
}
public int CreateAsync(string user, string password)
{
return 0;
}
}
Interface for UserStore
public interface IUserStore<T> where T : ApplicationUser
{
}
Actual UserStore
public class UserStore<T> : IUserStore<T> where T : ApplicationUser
{
}
Unity configuration
container.RegisterType(typeof (IUserManager<>), typeof (UserManager<>));
container.RegisterType(typeof (IUserStore<>), typeof (UserStore<>));
Hope this helps.
There is obviously lots that is not the same as your app, i.e. not doing the method call async, not reading the password in from the model, etc. but it should give an idea of how to solve the problem that you outlined.
This solution will give you proper constructor dependency injection, which will allow you to have all of your configuration in one place (i.e. the container config) and it will give you interfaces in your constructors which will make it much easier for you to mock those dependencies in your unit tests.
Cheers Mike

How to get resource from ninject without using constructor pattern in mvc3

When using Ninject with mvc3 we do something like, install ninject, registerger modules-or-services .
We write control like this
public class HomeController : Controller
{
private IHelloService _service;
public HomeController(IHelloService service)
{
_service = service;
}
public string Index()
{
return _service.GetGreeting();
}
}
I want to do something like
public class HomeController : Controller
{
private IHelloService _service;
/*
No default constructor
*/
public string Index()
{
_service= Ask_Ninject_to_provide_resource
return _service.GetGreeting();
}
}
Your current practice of writing controls is better than what you are proposing. You want to be able to inject through fields, rather than constructor. This is a bad idea and it's not recommended.
Quote from Ninject wiki:
"Although its simplicity is tempting, you should generally try to avoid using field injection, since the value can then only be set via Ninject. This makes unit testing much more complex, since sometimes it's easiest to use dependency injection by hand to inject mock objects into your unit tests. (Unit testing with Ninject is covered in more depth later.)"
Alternative is to inject through properties, but once again, you have to have a very good reason to do so. Most of the time constructor injection should do the job.
public class HomeController : Controller
{
private IHelloService _service;
/*
No default constructor
*/
public string Index()
{
_service= DependencyResolver.Current.GetService<IHelloService>();
return _service.GetGreeting();
}
}
Though I would seriously question the need to do this.

Categories

Resources