Webforms and Dependency Injection - c#

I am in the process of introducing a Dependency Injection framework into an existing WebForms application (using Castle Windsor).
I have pretty deep experience with DI, and tend to very strongly favor constructor injection over setter injection. If you are familiar with Webforms, you know that the ASP.Net framework handles the construction of page and control objects, making true constructor injection impossible.
My current solution is to register the container in the Application_Start event of the Global.asax, and keep the container as a public static variable in Global as well. I then simply resolve each service that I need directly in the page or control when I need them. So at the top of each page, I end up with code like this:
private readonly IMyService _exposureManager = Global.IoC.Resolve<IMyService>();
private readonly IMyOtherService _tenCustomersExposureManager = Global.IoC.Resolve<IMyOtherService>();
Obviously, I don't like having all these references to the container scattered about my application or having my page/control dependencies be non-explicit, but I have not been able to find a better way.
Is there a more elegant solution for using DI with Webforms?

I agree with #DarinDimitrov that MVP is an interesting option. However, when working with a legacy application, rewriting an existing page to the MVP pattern is a hell of a job. In that case it might be better to start with the Service Locator pattern (but only in your UI classes) as you are already doing. However, do change one thing. Do not expose the chosen DI container to the application, as I expect you are doing with the Global.IoC property.
Instead, create a static Resolve<T> method on the Global class. This hides the container completely and allows you to swap implementations without having to change anything in your web pages. When you do this, there is no advantage in using the Common Service Locator as #Wiktor proposes. The Common Service Locator is just another abstraction for something that doesn't have to be abstracted (since you've already abstracted away the container using the Global.Resolve<T>).
Unfortunately with Web forms, there is not really any good way to do this. For Simple Injector, I wrote an integration guide for Web Forms that basically describes the use of the Global.Resolve<T> method, but also shows a way to tests if Page classes can be created. The guide can be used for other DI containers as well.
BTW, please keep in mind that with Castle Windsor, everything you request must be released explicitly (the Register Resolve Release pattern). This is a bit nasty (IMO) and differs from how other containers work and can be a source of memory leaks when you do not do this correctly.
Last note. It is possible to do constructor injection with Web Forms. Well... sort of, since this will call the overloaded constructor using reflection after the Form has been created using the default constructor, so this causes Temporal Coupling.

Is there a more elegant solution for using DI with Webforms?
Yeap, the MVP pattern allows you to have a clean separation of concerns in a WebForms application. And once you have separation of concerns and weak coupling, DI is easy.
And in ASP.NET MVC that's built-in.

Know that this is pretty old, but now, there is DI in WebForms starting in .NET 4.7.2. Regarding to this article: ASP.NET Blog: Use Dependency Injection In WebForms Application
Just install Microsoft.AspNet.WebFormsDependencyInjection.Unity package and registr your classes in Global.asax:
protected void Application_Start(object sender, EventArgs e)
{
var container = this.AddUnity();
container.RegisterType<IPopularMovie, MovieManager>();
container.RegisterType<IMovieRepository, XmlMovieRepository>();
}
Hope it help.

ASP.NET MVC has IDependencyResolver and a static manager class that lets you get and set the resolver. I didn't like the idea of referencing System.Web.Mvc in a web forms project, so I went with IServiceLocator, which does about the same thing:
public static class Bootstrapper
{
private static readonly IUnityContainer _container = new UnityContainer();
public static void Initialize()
{
ServiceLocator.SetLocatorProvider(() => new UnityServiceLocator(_container));
_container.RegisterType<IDriverService, DriverService>();
}
public static void TearDown()
{
_container.Dispose();
}
}
public class Global : HttpApplication
{
protected void Application_Start(object sender, EventArgs e)
{
Bootstrapper.Initialize();
}
protected void Application_End(object sender, EventArgs e)
{
Bootstrapper.TearDown();
}
}
Then in your Page class ...
IDriverService service = ServiceLocator.Current.GetInstance<IDriverService>();
Or wire up DI via constructor injection. I haven't gone down that road with web forms yet, so someone else will need to fill in for me :) (I've been living mostly in MVC land for about a year now).
My example uses Unity, but you should be able to adapt it to any other DI implementation fairly easily.

As #DarinDimitrov says the MVP pattern is the way to go in order to use DI/IOC with Webforms.
Either you can roll your own implementation or use an existing framework. I've heard good about Webforms MVP, but I haven't actually used it.
According to the docs, it has built in support for DI via Castle Windsor, Autofac and Unity. It also has convention based auto discovery for Presenters.

Actually, what you have just built is your own implementation of the Service Locator. But, almost for sure, an implementation already exists for a IoC framework of your choice.
http://commonservicelocator.codeplex.com/

Related

UWP MVVM Template10: Access single instance of external API across application

I've been tasked with taking over a partially developed sizeable and complex UWP application using MVVM via Template 10. The app needs to use an in-house developed webservices API and this needs to be used for practically every single function, starting with the initial login page.
So given I need to access a single instance of the API everywhere how do I go about doing that correctly? I've used MVVM a fair bit but never used Template10 and never had to share an instance of an object across an entire MVVM UWP app before.
So far I can think of three ways:
Declare and instantiate API instance in Appl.xaml.cs and use it globally
Create a public Globals class and have the instance as a public static property:
c#
public class Globals
{
private static OurAPI _ourAPI;
public static OurAPI API
{
get { return _ourAPI; }
set { _ourAPI = value; }
}
}
Instantiate the API in the login page and then pass it as a parameter between ViewModels, presumably using the Navigation service.
I'm thinking 1 or 2 are most likely not MVVM compliant and could cause unit testing issues so maybe 3 is the best option? Or is there another, more correct way to do this to adhere to Template10/MVVM concepts and also be able to unit test it?
EDIT: Sorry about the code not formatting, the edit box formats it Ok but when I save it it goes back to one long sentence :-(
The best solution consists of a singleton service and inversion of control (IoC) / Dependency injection . This is a pretty complex topic so I definitely encourage to read about it from several sources.
In summary, you first create an interface for your service, where you declare all the public members and methods. Then you create an implementation of the interface. Then you use a IoC container and register your service as a singleton (single-instance) and then integrate the IoC so that it creates instances of your view models. Then you can put the interface as a constructor parameter of your view model and the IoC container will make sure to provide the singleton instance you registered.
In your case, you are using Template 10 which can be integrated with different IoC containers as seen in the documentation. Check out AutoFac as an example of an IoC container. You can see some examples of registering and resolving a service in the documentation.
For a general solution, check this SO question which demonstrates using AutoFac in UWP.
You can also see some code examples in this SO question and this one specifically for Template 10.
This solution is better than using static and global instances because you never actually deal with any hardcoded reference and actually always work just against the interface. You put the interface as the parameter of your constructor and IoC will take care of providing the instance for you. In addition - you can anytime swap the interface implementation for a different class and you just have to update it in one single location - the IoC registration.

Asp.Net core: Get required service via depedency injection in non-controller libraries. E.g. C# Common library

As I am using default dependency inject functionality of Asp.net core, it works great by resolving dependency via Constructor.
E.g.
Registration:
public static void AddServices(this IServiceCollection services, IConfigurationRoot configuration)
{
services.AddScoped<ICookieManager, CookieManager>();
}
Access via constructor:
protected ICookieManager CookieManager { get; set; }
public HomeController(ICookieManager cookieManager)
{
this.CookieManager = cookieManager;
}
The above code works great!
Now, I have a library called Library.Common where I have some common functionality written which can be used by different project.
In my common library code, how would I resolve the dependency without constructor?
I want something like this:
public void CalculateOrder()
{
var cookieManager = ServiceLocator.Instance.GetService<ICookieManager>();
}
Would anybody help me to find out how would I resolve the dependency without constructor in Asp.net core? Like resolving in common library, in static methods without constructor.
Thanks in advance!
Leave it as a constructor injected dependency. If your common library is to be used across multiple projects where DI is used it will work fine (assuming you configure the DI container correctly). If DI is not used you can simply construct an instance of an ICookieManager implementation and pass it into the constructor as an argument.
You could also consider using property injection for the dependency, although this would be most suitable where your method, CalculateOrder(), can still provide some functional value without the ICookieManager dependency.
The existing answer is correct in saying that it's probably better for a multitude of reasons to use constructor DI. If this is a new project inside .NET Core, you are better off doing things right from the start.
That being said, if you have an extreme need for using ServiceLocator or you are migrating a project across and you don't want to have to redo everything in one go to use constructor DI, you can simply create a static ServiceLocator class that uses .NET Core's injectable DI.
An example of this is here : https://dotnetcoretutorials.com/2018/05/06/servicelocator-shim-for-net-core/ Where you just create a static class that simply runs the "GetService" method from .NET Core's Service Collection.

Is there a workaround for dependency injection in a class library?

I have a class library that internally I have structured to use dependency injection (ninject). It's used by a variety of projects; MVC, windows services, REST apis etc.
I simply have a class like so:
public class KittenInvestigator
{
[Inject]
public IKittenDetectorDevice KittenDetectorDevice { get; set; }
...
}
Googling the issue to death I have found it to be impossible to initialise ninject in a class library as there is no 'startup' method or hook.
I'm looking for a workaround. There are tons of posts about the issue but I can't find any solutions or workarounds. Any ideas?
Some things I have considered:
Put the bindings into the project referencing the library. This is super bad since the injection is used internally in the library such that external components should never know about it - they'd have to magically know to add these bindings or the library won't work.
Some kind of reflection, making my ninject code in the main project scan all assemblies for ninject modules and initialise them.
A static initialise method in the class library that must be called by the main project that will set up the ninject stuff (seems tacky).
Some other clever design.
You could have a startup method, create a static class called bootstrapper and do the composition of your DI container in the static constructor.
You could use Fody.ModuleInit to bootstrap the library automatically when its assembly is loaded. But i would not recommend it and instead do either of:
go the explicit way as described by Mark Seeman (and to which Steven already has provided a link as a comment to your post: DI friendly library
After carefully weighing the advantages and disadvantages opt to use ninject modules and use Dynamic Module Loading or something similar but custom.

MVC5 Identity with DI (Removing Service Locator anti-pattern)

I am trying to remove the Service Locator Anti Pattern that comes by default with a new MVC5 project. I am attempting to implement DI instead using Ninject. I have come upon the following guide which is meant for unity, not an MVC5 application.
http://tech.trailmax.info/2014/09/aspnet-identity-and-ioc-container-registration/
From what I can tell, there is not too much difference in code between that article and a new MVC5 application. However there is one thing that I cannot seem to figure out what to do with.
In the article I provided above exists the following method
private static void RegisterTypes(IUnityContainer container)
{
container.RegisterType<ApplicationDbContext>();
container.RegisterType<ApplicationSignInManager>();
container.RegisterType<ApplicationUserManager>();
}
I am trying to understand what this container is and what I would register my classes to in MVC5. Do I need to register my classes to some container to begin with? Still learning here and I'm quite new to MVC5 and Identity so any help is most appreciated.
The container contains configuration settings for each abstraction and its implementation. The container is used to create dependencies and inject them automatically when required. Whenever there is a need of instance of an abstraction, the container provides that to the requester. It automatically creates objects based on request and inject them when required. The container helps to manage dependencies with in the application in a simple and easy way.

Dependency injection or service location?

I'm trying to learn dependency injection, and there are many subtleties to it I'm yet to grasp. One of the books that I've started reading for that purpose is "Foundations of Programming" by Karl Seguin. There's an example about dependency injection:
public class Car
{
private int _id;
public void Save()
{
if (!IsValid())
{
//todo: come up with a better exception
throw new InvalidOperationException("The car must be in a valid state");
}
IDataAccess dataAccess = ObjectFactory.GetInstance<IDataAccess>();
if (_id == 0)
{
_id = dataAccess.Save(this);
}
else
{
dataAccess.Update(this);
}
}
}
And then he goes ahead and suggest adding another level of indirection, rather than calling ObjectFactory directly in the method:
public static class DataFactory
{
public static IDataAccess CreateInstance
{
get
{
return ObjectFactory.GetInstance<IDataAccess>();
}
}
}
But isn't this "Service Location" in fact?
It is service locator. There are several of ways to use dependency:
aggregation (example case)
composition
DI in constructor, mandatory (could be injected using SL on upper level)
DI in property, optional (could be injected using SL on upper level)
What to choose depends on many factors, for example whether it is stable or unstable dependency, whether you need to mock it in tests or not etc. There is good book on DI called 'Dependency Injection in .NET' by Mark Seemann.
Yes, looks like SL to me. Dependency injection traditionally follows one of two patterns; property injection or constructor injection.
Dependency injection feels more effort than service location at first, but service location (SL) has a number of negatives. It is far too easy with a service locator to just go crazy requesting services on a whim, all over the place. This is fine until you go to refactor and realise the coupling is "too damn high".
With DI I prefer the constructor injection form because it forces me to think up front about who needs what.
That all said, my current project was started as a green field project using a service locator because it gave me the flexibility "not" to think about dependencies and to let the application shape evolve. Latterly I've been refactoring to use DI, mainly to get a handle on what relies on what and why.
Your example is ServiceLocator. There is always a ServiceLocator somewhere. I would say the key is to understanding why you would use it directly and why ideally you might not have to.
The key concept is the dependency inversion principal. Dependency injection and inversion of control frameworks are tools that facilitate application of the principal. Ideally you want your objects constructor parameters to be interface definitions which will be resolved at object creation time.
If you are using modern tools, such as asp.net MVC then you have access to what is called the composition root which is the entry point of the application. In MVC it's controller. Since you have access to the composition root you don't need to use ServiceLocator because injection is driven from the top for you by your IOC framework which you would have registered and setup. Basically your controller has constructors parameters like ISomeService which is registered with IOC and injected automatically when the controller instance is created. If the ISomeService had some dependencies they would also be in the constructor as ISomeUtility, and so forth as your objects get deeper and deeper. This is ideal and you would never have need to use the ServiceLocator to resolve an object.
If you were in a situation using technology that doesn't grant you access to the root or if you were wanting to start using an IOC framework in an application that didn't have one and you were adding it for the first time then you may find you can't get to the composition root. It could be a limitation of the framework or the quality of the code. In these cases you have to use the ServiceLocator or directly create the object yourself. In these cases using the ServiceLocator is OK and is better than creating that object yourself.

Categories

Resources