IoC and ASP.NET MVC Controllers - c#

Should I do something along the lines of this? I'm thinking of all my controllers inheriting from BaseController. Does this break the design pattern of IoC? What else should I do instead?
public class BaseController: Controller
{
protected ICookieService CookieService {
get {
return ServiceResolver.Resolve<ICookieService>(new { HttpContext = HttpContext });
}
}
protected IDateTimeService DateTimeService {
get {
return ServiceResolver.Resolve<IDateTimeService>();
}
}
protected ISettingsService SettingsService {
get {
return ServiceResolver.Resolve<ISettingsService>();
}
}
}

It would be a lot simpler to go with constructor injection and have a controllerfactory inject it for you. If you can, don't use a service locator (your ServiceResolver ) if you can get away with constructor injection.
There's some info on it on Adding a controller factory to ASP MVC
The link shows how to do it with StructureMap and it looks like you're using Unity, but it should be straightforward to adapt.

I'm assuming that the protected interfaces you have are dependencies for the controller. Its possible to set up an IoC container to inject the dependencies for you. It can certainly be done with Castle Windsor. You would need to change you BaseController class to have a constructor with the required dependencies, as long as the IoC container knows about the other services it'll be able to inject them.

One of the principles behind Inversion of Control and Component-Driven Development is about using static service locators only when there is no other way (i.e.: in web service hosts or object data sources).
Technically speaking, using static service locators the base controller does not violate IoC, it just does not use it.
Check out existing integration between Autofac IoC container and ASP.NET MVC (other containers should be able to do that as well).

Related

How to set up controller so constructor gets called with repository argument

Having soured books, I can't figure out what in a C# MVC project I'm taking over causes the Controller constructors to always be passed a repository argument.
public partial class AdminController : ApiController
{
IDataRepository _repo;
public AdminController(IDataRepository repo)
{
_repo = repo;
}
}
Even other classes who are NOT partials are written this way.
I have looked at the class (or Interface) that these inherit from.
Any ideas?
Thanks in advance.
This is called dependency injection.
Asp.net core has a built-in DI container. But for old Asp.net projects, you should add a library to use this. I don't know which library you use, but I can give some common examples:
Simple Injector
https://simpleinjector.readthedocs.io/en/latest/aspnetintegration.html
// You'll need to include the following namespaces
using System.Web.Mvc;
using SimpleInjector;
using SimpleInjector.Integration.Web;
using SimpleInjector.Integration.Web.Mvc;
// This is the Application_Start event from the Global.asax file.
protected void Application_Start(object sender, EventArgs e) {
// Create the container as usual.
var container = new Container();
container.Options.DefaultScopedLifestyle = new WebRequestLifestyle();
// Register your types, for instance:
container.Register<IUserRepository, SqlUserRepository>(Lifestyle.Scoped);
// This is an extension method from the integration package.
container.RegisterMvcControllers(Assembly.GetExecutingAssembly());
container.Verify();
DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container));
}
Castle Windsor
https://gist.github.com/martinnormark/3128275
public class ControllersInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(AllTypes.FromThisAssembly()
.Pick().If(t => t.Name.EndsWith("Controller"))
.Configure(configurer => configurer.Named(configurer.Implementation.Name))
.LifestylePerWebRequest());
}
}
Asp.net Core
https://learn.microsoft.com/tr-tr/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-2.2
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.AddScoped<IMyDependency, MyDependency>();
}
Like others have said, dependency injection. But some more details:
.net framework and .net core handle it differently.
It's not built in at all in the .net framework. You'll want to check you global.asax file to figure out whats going on. Most of the time its done through a nuget package. there are many popular ones like autofaq, ninject, simple injector etc. You should see some stuff about building a container and registering services.
.net core has its own dependency injection framework it ships with, so quite often that's used. Although sometimes people still use a nuget package for something more complex. The .net core stuff will be in the Startup.cs file. See if theres anything like services.AddTransient anywhere.
It's possible, though unlikely someone wrote there own dependency injection framework in your project. In that case you'd be looking for them to have written a ControllerFactory implementation.
If you can't figure it out from here, please add either the global.asax file, or the startup.cs file to your question.
This is Dependency Injection, have a look in startup for something like
services.AddTransiant<IDataRepository, DataRepo>();
This tells the dependency injection container to instantiate IDataRepository with an instance of DataRepo.

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

Who instantiates the test class in a test class project?

I am writing some integration tests. I am using Dependency Injection with Windsor Castle.
I would like to resolve the test class using an inversion of control container. I do not think that resolve all my dependencies inside the test class is the solution for my case.
I would like to do what I have done inside the web api project. I implemented IHttpControllerActivator, which is an extension point to fully control controller's life-cycle. That is, we can define how a controller is instantiated.
I would like to do the same for the tests. But I do not understand which is the interface I have to implement. Can anyone help me?
I think I just need to know which is the corresponding IHttpControllerActivator for unit test.
EDIT
I have a web api project to test. The web api project resolves all the dependencies with WindsorCastle. Now I need to test the web api. This is what I am doing:
public voi MyTest_Ok()
{
//Arrange
var myController = new MyWebApiController();
var result = await myController.DoWork();
//Asserts
}
Obviously it does not work because I am not using castle windsor to resolve the controller and so I do not resolve any dependency from web api controller to bottom.
I think I could replace this line
var myController = new MyWebApiController();
with something like this
var myController = windsorContainer.Resolve<MyWebApiController>();
But this solution I think is wrong. I think it's better to resolve dependencies as happen inside the controller:
public class MyWebApiController : ApiController()
{
public InjectedDependency dep { get; set; }
public DoWork()
{
dep.DoWork();
}
}
I can do this because I have implemented a custom IHttpControllerActivator.
Answer is: your test framework does. As I know none of the common test frameworks allows you take control over creating your test classes.
More info about this here as well:
A .NET Unit Test without a parameterless constructor, to facilitate dependency injection
NUnit provide ParameterizedTestFixture -https://github.com/nunit/docs/wiki/TestFixtureData
So in theory as a dirty workaround you would be able to inject some dependencies trough constructor by this, but it wasn't designed for this purpose.
In general you have to go for service locator.

IPrincipal Dependency Injection in MVC5

In another stackoverflow question MVC5 IoC and Authentication the first answer states the author uses Dependency Injection to inject the IPrincipal. I would love to do this for my assemblers so that I don't have to pass the current user (IPrincipal) from the controller.
Can anyone give an example of how to use DI to inject the IPrincipal in C# MVC5? Below is the IoC I first want to implement it in. Added after first answer given.
public class ViewModelAssemblersInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(
Component.For<IAspNetUserAssembler>()
.ImplementedBy<AspNetUserAssembler>());
}
}
For Castle Windsor, it's something like:
container.Register(Component.For<IPrincipal>()
.LifeStyle.PerWebRequest
.UsingFactoryMethod(() => HttpContext.Current.User));
Its going to be dependent on your IoC container... for me, I use Unity, and in my container registration I'm able to do the following:
container.RegisterType<IPrincipal>(new InjectionFactory(u => HttpContext.Current.User));
Using the InjectionFactory, unity will execute the lambda to return the current HttpContext.Current.User at the time of constructor injection. I'm also able to use the same type of registration in my non web applications, instead referencing the Thread.CurrentPrincipal.

Using a parameterless controller constructor with Ninject?

I'm using Ninject for dependency injection in my application. Here's an example of one of my controllers:
public class DepartmentsController : Controller
{
private IDepartmentsRepository departmentsRepository;
public DepartmentsController(IDepartmentsRepository departmentsRepository)
{
this.departmentsRepository = departmentsRepository;
}
...
}
I'm also trying to follow this tutorial to use ELMAH in an MVC application. The idea is to use a custom controller factory to handle errors from every controller. You then set the controller factory to the custom one in the global.asax.cs file.
The only problem is that it is expecting a parameterless constructor in each controller, which I can't do (that I know of) with dependency injection with Ninject.
How can I get around this?
If you are using MVC3, you should ignore the part about the Controller Factory and use Global Filters to apply the custom attribute to each controller.
If you aren't using v3 yet and you can modify their code to inherit from the Ninject Controller factory.

Categories

Resources