Using Unity.WebForms in ASP.NET - dependency-injection

I am trying to implement DI in a webforms project, so I installed the Unity.WebForms dlls in my UI layer. As soon as I did an App_Start folder was created for me with a UnityWebFormsStart class file. Inside this file there is a method RegisterDependencies which asks to be edited.
What is the next step after registering the dependencies? Is there something I need to add in the Global.asax class file? And how and where do I resolve a type inside a webform? Do I decorate that with any attributes?

The Unity.WebForms dll and NuGet package does a few things for you in the background. It will ensure that a child container is started at the begin of each new web request and disposed at the end of each request. This allows you to register components with a 'per web request' lifestyle (using the HierarchicalLifetimeManager in Unity), which is useful for components such as O/RM unit of works such as Entity Framework's DbContext.
The other thing that the package ensures is that the given HttpHandler (usually your Page) and all its child controls are Built up. The BuildUp method is the way to initialize components that are not created by the container itself.
So the idea is to use property injection in your page classes and controls, but solely use constructor injection in ALL other components in your application. Constructor injection is the preferred mechanism for doing dependency injection, but constructor injection is unfortunately not possible in ASP.NET Page and Control classes.
So your page could look like this:
public class CancelOrderPage : Page
{
[Dependency]
public ICommandHandler<CancelOrder> CancelOrderHandler { get; set; }
void CancelButton_Click(object sender, EventArgs e) {
this.CancelOrderHandler.Handle(new CancelOrder {
OrderId = Guid.Parse(this.OrderIdHiddenField.Value)
});
}
}
For the rest of your application, use constructor injection:
public class CancelOrderHandler : ICommandHandler<CancelOrder>
{
private readonly IAuthorizedRepository<Order> orderRepository;
private readonly IEventPublisher eventPublisher;
public CancelOrderHandler(IAuthorizedRepository<Order> orderRepository,
IEventPublisher eventPublisher) {
this.orderRepository = orderRepository;
this.eventPublisher = eventPublisher;
}
public void Handle(CancelOrder command) {
// some implementation
}
}
In the RegisterDependencies you will have to register your dependencies. You can do this manually:
container.RegisterType<ICommandHandler<CancelOrder>, CancelOrderHandler>();
container.RegisterType<IEventPublisher, InProcessPublisher>();
container.RegisterType(
typeof(AuthorizedRepository<>),
typeof(DbContextRepo<>));
Or you can use batch-registration.

Related

ASP.NET MVC Boilerplate: Migrating from AutoFac to Unity, cannot get Services DI working again

Current project:
ASP.NET MVC 5 boilerplate (Github)
Switching Autofac out for Unity
When I switch the DI from AutoFac to Unity, I am unable to get the Services built into the boilerplate (robots.txt, sitemap.xml) back up and running. In particular, I am unable to translate the Autofac entries for these services to the appropriate Unity entries.
My HomeController default constructor is unchanged from the default, at least for robots.txt, which I am doing the litmus test on:
private readonly IRobotsService _robotsService;
public HomeController(IRobotsService robotsService) {
_robotsService = robotsService;
}
The robots.txt method in my HomeController is similarly default for the boilerplate:
[NoTrailingSlash]
[OutputCache(CacheProfile = CacheProfileName.RobotsText)]
[Route("robots.txt", Name = HomeControllerRoute.GetRobotsText)]
public ContentResult RobotsText() {
Trace.WriteLine($"robots.txt requested. User Agent:<{Request.Headers.Get("User-Agent")}>.");
var content = _robotsService.GetRobotsText();
return Content(content, ContentType.Text, Encoding.UTF8);
}
The IRobotsService and RobotsService files are also default for the boilerplate - they are completely unmodified (aside from removing comments for brevity):
namespace Project.Website.Services {
public interface IRobotsService {
string GetRobotsText();
}
}
namespace Project.Website.Services {
using Boilerplate.Web.Mvc;
using Constants;
using System.Text;
using System.Web.Mvc;
public sealed class RobotsService : IRobotsService {
private readonly UrlHelper _urlHelper;
public RobotsService(UrlHelper urlHelper) => _urlHelper = urlHelper;
public string GetRobotsText() {
var stringBuilder = new StringBuilder();
stringBuilder.AppendLine("user-agent: *");
stringBuilder.AppendLine("disallow: /error/");
stringBuilder.Append("sitemap: ");
// Commented out so it wouldn't trigger the sitemap, which is not active:
//stringBuilder.AppendLine(_urlHelper.AbsoluteRouteUrl(HomeControllerRoute.GetSitemapXml).TrimEnd('/'));
return stringBuilder.ToString();
}
}
}
The original Startup.Container.cs for Autofac is quite extensive, but the robots.txt service is injected by:
builder.RegisterType<RobotsService>().As<IRobotsService>().InstancePerRequest();
When my UnityConfig.cs file has the following:
container.RegisterType<RobotsService>(new TransientLifetimeManager());
I get
The current type, JCI_Vernon.Website.Services.IRobotsService, is an interface and cannot be constructed. Are you missing a type mapping?
Which pretty well tells me I have to include IRobotsService, but when my UnityConfig file has the following:
container.RegisterType<IRobotsService, RobotsService>(new TransientLifetimeManager());
I get
The current type, System.Web.HttpContextBase, is an abstract class and cannot be constructed. Are you missing a type mapping?
I am unsure as to where I am going wrong, as all other Unity DI in my project is configured by using one of these two variants.
Any assistance would be greatly appreciated.
Edit: Including the Unity files from my primary project (the visible website).
UnityMvcActivator.cs:
[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(JCI_Vernon.Website.UnityMvcActivator), nameof(JCI_Vernon.Website.UnityMvcActivator.Start))]
[assembly: WebActivatorEx.ApplicationShutdownMethod(typeof(JCI_Vernon.Website.UnityMvcActivator), nameof(JCI_Vernon.Website.UnityMvcActivator.Shutdown))]
namespace JCI_Vernon.Website {
using System.Linq;
using System.Web.Mvc;
using Unity.AspNet.Mvc;
/// <summary>
/// Provides the bootstrapping for integrating Unity with ASP.NET MVC.
/// </summary>
public static class UnityMvcActivator {
/// <summary>
/// Integrates Unity when the application starts.
/// </summary>
public static void Start() {
FilterProviders.Providers.Remove(FilterProviders.Providers.OfType<FilterAttributeFilterProvider>().First());
FilterProviders.Providers.Add(new UnityFilterAttributeFilterProvider(UnityConfig.Container));
DependencyResolver.SetResolver(new UnityDependencyResolver(UnityConfig.Container));
// TODO: Uncomment if you want to use PerRequestLifetimeManager
// Microsoft.Web.Infrastructure.DynamicModuleHelper.DynamicModuleUtility.RegisterModule(typeof(UnityPerRequestHttpModule));
}
/// <summary>
/// Disposes the Unity container when the application is shut down.
/// </summary>
public static void Shutdown() {
UnityConfig.Container.Dispose();
}
}
}
UnityConfig.cs:
namespace JCI_Vernon.Website {
using Data;
using Domain;
using Identity;
using Microsoft.AspNet.Identity;
using Services;
using Store;
using System;
using System.Web;
using System.Web.Mvc;
using Unity;
using Unity.Injection;
using Unity.Lifetime;
using Unity.Mvc5;
public static class UnityConfig {
public static IUnityContainer Container { get; internal set; }
public static void RegisterComponents() {
var container = new UnityContainer();
container.RegisterType<IUnitOfWork, UnitOfWork>(new HierarchicalLifetimeManager(), new InjectionConstructor("DefaultConnection"));
container.RegisterType<IUserStore<IdentityUser, Guid>, UserStore>(new TransientLifetimeManager());
container.RegisterType<RoleStore>(new TransientLifetimeManager());
container.RegisterInstance<HttpContextBase>(new HttpContextWrapper(HttpContext.Current), new TransientLifetimeManager());
container.RegisterType<IRobotsService, RobotsService>(new Unity.AspNet.Mvc.PerRequestLifetimeManager());
//container.RegisterType<ISitemapService, SitemapService>(new InjectionConstructor());
//container.RegisterType<ISitemapPingerService, SitemapPingerService>(new InjectionConstructor());
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}
}
}
In my UnityMvcActivator.cs, I have had that one PerRequestLifetimeManager line both commented and uncommented with every change, no difference observed. Any attempt to use PerRequestLifetimeManager within UnityConfig.cs without Unity.Mvc (as using Unity.AspNet.Mvc;) failed.
Changing UnityConfig.cs to include Unity.AspNet.Mvc caused mass borkage: while I was able to get PerRequestLifetimeManager to be accepted without obvious Intellisense error, UnityMvcActivator.cs suddenly couldn’t resolve its UnityConfig.Container entries without a very odd entry at the top of UnityConfig.cs:
public static IUnityContainer Container { get; internal set; }
And the SetResolver in UnityConfig.cs needed to explicitly state new Unity.Mvc5.UnityDependencyResolver(container) in order to not trigger Intellisense confusion.
Plus, when run, the following error occurred:
Could not load file or assembly 'Unity.Abstractions, Version=3.1.3.0, Culture=neutral, PublicKeyToken=6d32ff45e0ccc69f' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
Why it is trying to target a v3.x of Unity despite the entire solution having been created under v5.x is causing my grey matter no end of meltdown. And yes, I did a full clean and rebuild of the entire solution, plus individual projects.
Edit 2:
May have come across an interesting wrinkle. On a lark, I decided to do a full reinstallation of all NuGet packages, a refresh of sorts. Naturally, when you do an upgrade or reinstall of Unity, it tries to overwrite your unity files, which is why you always need to have your UnityConfig.cs backed up otherwise your registrations will vanish. Happens to me with every. Single. F##cking. Project. So annoying.
So anyhow, I did a full refresh, and my UnityConfig.cs suddenly underwent a major change. Before it was as above, including all upgrades within v5, but the refresh provided me with the following (comments removed for brevity):
namespace JCI_Vernon.Website {
using System;
using Unity;
public static class UnityConfig {
#region Unity Container
private static Lazy<IUnityContainer> container =
new Lazy<IUnityContainer>(() => {
var container = new UnityContainer();
RegisterTypes(container);
return container;
});
public static IUnityContainer Container => container.Value;
#endregion
public static void RegisterTypes(IUnityContainer container) {
// TODO: Register your type's mappings here.
// container.RegisterType<IProductRepository, ProductRepository>();
}
}
}
Ya, weird. Major change with no clue why. The old version works just fine, it just blows its cookies all over the specific type mapping this post is about.
Plus, I have to idea what to change the Global.cs entry to in order to load my type mappings, as just using the obvious (changing UnityConfig.RegisterComponents(), which cannot be found, to UnityConfig.RegisterTypes()) does not make any sense -- how do I pass in the container?
There are a couple of issues here. First of all, this line:
container.RegisterType<RobotsService>(new TransientLifetimeManager());
is not the equivalent of:
builder.RegisterType<RobotsService>().As<IRobotsService>().InstancePerRequest();
It should instead be:
container.RegisterType<IRobotsService, RobotsService>(new TransientLifetimeManager());
Keep in mind Autofac type mappings use the concrete type first, and then the interface type. This is backward from most other DI containers.
The last error message indicates you need to register HttpContextBase with Unity. You do that by wrapping HttpContext.Current with HttpContextWrapper.
container.RegisterInstance<HttpContextBase>(new HttpContextWrapper(HttpContext.Current), new TransientLifetimeManager());

How to share the same instance in ASP.NET MVC 5 with Ninject?

I am trying to use Ninject for IoC with ASP.NET MVC 5.
My controller has a constructor like this:
private readonly IUnitOfWork _unit;
private readonly IContactService contactService;
public ContactsController(IUnitOfWork unit, IContactService contactService)
{
this._unit = unit;
this._contactService = contactService;
}
So the ContactService has a constructor (IUnitOfWork unit) and should share the same instance of the IUnitOfWork, but Ninject is giving a new different instance. My ContactService derives of a class with this constructor:
public ServiceBase(IUnitOfWork unit)
{
_unit = unit;
_repository = _unit.GetRepository<TEntity>();
}
My ninject config bindings:
public static void RegisterServices(IKernel kernel)
{
kernel.Bind<IUnitOfWork>().To<UnitOfWork>().InRequestScope();
kernel.Bind<IContactService>().To<ContactService>().InRequestScope();;
}
I hope that InRequestScope() give the same instance per request, but that is not happening.
I had exactly the same problem now. I had Ninject and Ninject.Web.Common packages installed and I was injecting dependencies using my custom NinjectControllerFactory. Using Erik's response linked by BatteryBackupUnit's in comments, I have decided to uninstall my Ninject packages and I have installed Ninject.MVC5 package.
The package generated a NinjectWebCommon.cs Ninject confgiuration file in the App_Start folder. The only thing you need to do is to copy your bindings to RegisterServices method in NinjectWebCommon.cs file and stop using your custom NinjectControllerFactory (if you have one).
It solved my problem, hope it solves your problem as well.

ASP.NET MVC + Ninject: InRequestScope

I want to create instance of PerRequestResourceProvider using ninject InRequestScope:
public class PerRequestResourceProvider: IPerRequestResourceProvider
{
priavte readonly _perRequestResorceInstance;
public PerRequestResourceProvider()
{
_perRequestResorceInstance = new PerRequestResource();
}
public PerRequestResource GetResource()
{
return _perRequestResorceInstance;
}
}
public interface IPerRequestResourceProvider
{
PerRequestResource GetResource();
}
In my NinjectDependencyResolver:
.....
kernel.Bind<IPerRequestResourceProvider>.To<PerRequestResourceProvider>().InRequestScope();
I inject IPerRequestResourceProvider in few classes. But when I add breakpoint to PerRequestResourceProvider constructor I see that PerRequestResourceProvider is created three times during one request and not single per request. What's wrong?
Update: source code ttps://bitbucket.org/maximtkachenko/ninjectinrequestscope/src
There are two issues with your code:
Ninject is not getting initialized correctly.
You need one of the Ninject.MVCx packages (according to the MVC version you are using). To configure it correctly, see: http://github.com/ninject/ninject.web.mvc
You are injecting PerRequestResourceProvider (the class type), and not IPerRequestResourceProvider (the interface type) into HomeController, thus the .InRequestScope() defined on the IPerRequestResourceProvider binding is not taking any effect. Change the HomeController constructor to get the inteface type injected and you're good.
Ninject does not require bindings for instantiatable (non-abstract,..) classes. This is why it is not obvious when the wrong binding is used.

How to implement UnitOfWork with Onion Architecture without introducing dependencies?

I am setting up an asp.Net Mvc 4 app and looking to configure it using the Onion Architecture Pattern.
In the past I have used the Unit of Work Pattern like this
public class UnitOfWork : IUnitOfWork, IDisposable
{
private IRepository<CallModel> _callRepo;
private IRepository<UserModel> _userRepo;
public IRepository<CallModel> CallRepo
{
get
{
if (_callRepo == null)
{
_callRepo = new Repository<CallModel>();
}
return _callRepo;
}
}
public IRepository<UserModel> UserRepo
{
get
{
if (_userRepo == null)
{
_userRepo = new Repository<UserModel>();
}
return _userRepo;
}
}
}
I would then pass the instance of the UnitOfWork Class to the Controller to do simple CRUD stuff like this.
public class QuestionsController : Controller
{
private IUnitOfWork _unitOfWork;
[Inject]
public QuestionsController(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
I have seperated the app into three projects.
Core
Infrastructure
Web
I have my Interfaces all in the Core project and the implementation of the IRepository interface in the Infrastructure project.
If I put the UnitOfWork Class in the Core Project then since it calls for a new Repository in the Infrastructure project I am creating a dependency from the Core to the Infrastructure.
If I include it in the Infrastructure then the Web project (which has the controllers) will have a dependency on the Infrastructure and the whole Solution ends up looking less like an Onion and more like spaghetti.
I have my Interfaces all in the Core project and the implementation of the IRepository interface in the Infrastructure project. If I put the UnitOfWork Class in the Core Project then since it calls for a new Repository in the Infrastructure project I am creating a dependency from the Core to the Infrastructure.
Hmm, not really. Your unit of work class should have a dependency on IRepository, not the Repository implementation itself. If you are using Dependency Injection, this should not pose a problem, as it should find the right type and provide it at runtime. I'm not sure whether the Onion architecture is even possible without using DI.
See david.s's answer as well, as this is exactly how I set things up--have a project for the sole purpose of wiring up dependencies.
What I do is have another project named DependencyResolution which has references to Core and Infrastructure an where I configure my IoC container. Then I can refence only DependencyResolution from the Web project.
I would do like david.s create project named DependencyResolution but let it referance Web, Core and Infrastructure.
In that project you could do:
[assembly: PreApplicationStartMethod(typeof(Start), "Register")]
namespace DependencyResolution
{
public static class Start
{
public static void Register()
{
UnityConfig.Register();
}
}
}
and to register DI.
namespace DependencyResolution
{
public static class UnityConfig
{
public static void Register()
{
DependencyResolver.SetResolver(new UnityDependencyResolver());
}
}
}
So no referance between Web and infrastructure is needed.
Best regards
For what it's still worth, I have implemented my own library that applies the UnitOfWork-pattern a little differently than I've seen in any code sample before, but I have found it to work very well in practice. In short: I kinda copied the way .NET Transactions work by creating a scope and then enlisting resources in the ambient unitofwork(-manager) where necessary. What basically happens is that when a new message/request is being handled, this code is executed:
public void Handle<TMessage>(TMessage message)
{
using (var scope = CreateMessageProcessorContextScope())
{
HandleMessage(message);
scope.Complete();
}
}
Now just as with transactions, as soon as the Thread is still inside the scope, an ambient UnitOfWork-controller is present in which all resources that are used and changed during the request can enlist dynamically. They do this by implementing the IUnitOfWork-interface that has two methods:
public interface IUnitOfWork
{
bool RequiresFlush();
void Flush();
}
Instances that implement this interface can then enlist themselves as follows:
MessageProcessorContext.Current.Enlist(this);
Typically, a Repository-class will implement this interface, and when it detects it's managed aggregates are changed/added/removed, it can enlist itself (double enlistments are ignored).
In my case, the framework assumes that you are using an IOC-framework that will resolve all message-handlers and repositories for you, so I made enlistment to the ambient unit of work controller easier by letting it inject an instance of the current IUnitOfWorkManager into the constructor where required. This way the dependencies of the unit of work manager and the actual pieces that require to be flushed (repositories, services, etc) are reversed:
internal sealed class OrderRepository : IOrderRepository, IUnitOfWork
{
private readonly IUnitOfWorkManager _manager;
private readonly Dictionary<Guid, Order> _orders;
public OrderRepository(IUnitOfWorkManager manager)
{
if (manager == null)
{
throw new ArgumentNullException("manager");
}
_manager = manager;
}
bool IUnitOfWork.RequiresFlush()
{
return _orders.Values.Any(order => order.HasChanges());
}
void IUnitOfWork.Flush()
{
// Flush here...
}
public void Add(Order order)
{
_orders.Add(order.Id, order);
_manager.Enlist(this);
}
}
As soon as a request has been handled succesfully (no exceptions thrown), scope.Complete() will be called which triggers the controller to check with all enlisted items whether they (still) need to be flushed (by calling RequiresFlush()), and if so, flushes them (by calling Flush()).
All in all, this allows for a very maintainable solution (in my perspective) in which new repositories and other dependencies can be added on the fly without changing any master unitofwork class, just like the TransactionManager doesn't need to know upfront which items may take part in any given Transaction.

Using Ninject with Udi Dahan's Domain Events

I'm using Ninject in an MVC project and am trying to implement Domain Events following Udi Dahan's pattern http://www.udidahan.com/2009/06/14/domain-events-salvation/
In the extract below, the "Container" is used to resolve all the event-handlers for the particular type of event that has been raised.
My question (& apologies if I am missing something basic) is how to do this with Ninject? In other words:
How does the "Container" get set in this static class?
Once I have a Container (Kernel?) what would be the Ninject syntax to resolve all the event handlers (which I'm assuming I would have to register before-hand in a Service Module)?
I keep reading in posts that only constructor injection should be used and everything recursively get resolved from that, and that accessing the Ninject Kernel is a no-no. So any advice on how to do this will be much appreciated.
Extract from the article
public static class DomainEvents
{
[ThreadStatic] //so that each thread has its own callbacks
private static List<Delegate> actions;
public static IContainer Container { get; set; } //as before
//Registers a callback for the given domain event
public static void Register<T>(Action<T> callback) where T : IDomainEvent
{
if (actions == null)
actions = new List<Delegate>();
actions.Add(callback);
}
//Clears callbacks passed to Register on the current thread
public static void ClearCallbacks ()
{
actions = null;
}
//Raises the given domain event
public static void Raise<T>(T args) where T : IDomainEvent
{
if (Container != null)
foreach(var handler in Container.ResolveAll<Handles<T>>())
handler.Handle(args);
if (actions != null)
foreach (var action in actions)
if (action is Action<T>)
((Action<T>)action)(args);
}
}
How does the "Container" get set in this static class?
You will have to set it during application startup:
DomainEvents.Container = kernel;
what would be the Ninject syntax to resolve all the event handlers:
You can do it like this, for instance:
Container.Get<IEnumerable<Handles<T>>>())
Udi's static DomainEvents class is an implementation of the Ambient Context anti-pattern (see DI PP&P chapter 5.3). In this case I would rather use dependency injection to inject an IDomainEvents abstraction into code that needs it, instead of letting code depend on a static instance.
The problem however is that your domain objects will need a dependency on the IDomainEvents and constructor injection is (probably) not possible. The trick is to use method injection in that case.
In other words, use constructor injection to inject the IDomainEvents into command handlers or services (or what ever you call your business logic that uses the methods on your domain objects) and pass that dependency into the domain object when calling a method that needs it (method injection).

Resources