Managing AutoFac object creation for UnitOfWork - asp.net-web-api

I am new to architecture, I am in the process of learning and designing an application end to end. I have the below architecture and am using Autofac to manage object creation.
All businessobject contracts have been setup on webapi startup and that is the only startup which can actually startup all my autofac configurations/modules.
I use UnitOfWork/Repository pattern and it resides beyond my business layer, I do not want to refer the UnitOfWork in my WebAPi but i cannot startup UnitOfWork otherwise.
Can someone please give me some inputs on what should be my architecture/design/autofac unitofwork implementation?

In App_start register web project specific dependencies (controllers, etc). Have a static method in BL layer which registers unit of work, repositories, etc. Call this static method in App_start when all the web dependencies are being registered as below:
//App_Start (web project)
var builder = new ContainerBuilder();
var config = GlobalConfiguration.Configuration;
MyProject.BusinessLayer.RegisterDependancies.Register(builder); <-- Register Unit of Work here in static BL method
builder.RegisterControllers(typeof(MvcApplication).Assembly);
builder.RegisterApiControllers(typeof(MvcApplication).Assembly);
builder.RegisterModule<AutofacWebTypesModule>();
builder.RegisterWebApiFilterProvider(config);
builder.RegisterModule(new AutofacModules.AutoMapperModule());
builder.RegisterModule(new AutofacModules.Log4NetModule());
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
//Static method in BL
namespace MyProject.BusinessLayer
{
public static class RegisterDependancies
{
public static void Register(ContainerBuilder builder)
{
builder.RegisterType<MyContext>().As<IDataContextAsync>().InstancePerLifetimeScope();
builder.RegisterType<UnitOfWork>().As<IUnitOfWorkAsync>().InstancePerLifetimeScope();
builder.RegisterGeneric(typeof(Repository<>)).As(typeof(IRepositoryAsync<>)).InstancePerLifetimeScope();
builder.RegisterAssemblyTypes(typeof(BusinessService).Assembly).Where(t => t.Name.EndsWith("Service")).AsImplementedInterfaces().InstancePerLifetimeScope();
}
}
}

Related

Unity interface mapping exception in web api

I am getting this exception while debugging code:
Resolution of the dependency failed, type = "Aqueduct.Interfaces.IMasterDataClient", name = "MDS".
Exception occurred while: while resolving.
Exception is: InvalidOperationException - The current type,
Aqueduct.Interfaces.IMasterDataClient, is an interface and cannot be constructed. Are you missing a type mapping?
At the time of the exception, the container code was:
Resolving Aqueduct.Interfaces.IMasterDataClient,MDS
Unity.config:
public static class UnityConfig
{
public static void RegisterComponents()
{
var container = new UnityContainer();
IUnityContainer myContainer = new UnityContainer();
// register all your components with the container here
// it is NOT necessary to register your controllers
// e.g. container.RegisterType<ITestService, TestService>();
myContainer.RegisterType<IMasterDataClient, MasterDataClient>("MDS");
myContainer.RegisterType<ILinksManager, LinksManager>("LDS");
GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);
}
}
Web Api controller:
using (var container = new UnityContainer())
{
container.Resolve<IMasterDataClient>("MDS");
container.Resolve<ILinksManager>("LDS");
}
MasterDataClient Interface Implementing class:
public class MasterDataClient : HalClient, IMasterDataClient, IHalClient, ICrestaClient
{
public MasterDataClient(IApiClient apiClient, IUriDispenser dispenser);
}
You have three problems here.
Problem 1. You're creating a new container:
using (var container = new UnityContainer())
{
container.Resolve<IMasterDataClient>("MDS");
container.Resolve<ILinksManager>("LDS");
}
This container will be empty and have 0 registrations. It's not the same container as you made your registrations to. There's a couple of ways to solve it:
Problem 1 - Solution 1: Don't inject the container. Inject the dependencies.
Instead of using the container you should inject your dependencies directly to your controller:
public class MyApiController : ApiController
{
IMasterDataClient _masterDataClient;
ILinksManager _linksManager
public MyApiController(IMasterDataClient masterDataClient, ILinksManager linksManager)
{
_masterDataClient = masterDataClient;
_linksManagerlinksManager;
}
}
This way you can avoid the service locator-pattern and your dependency to the container itself. If you're using named registrations you may need to use the Dependency-attribute.
With Unity how do I inject a named dependency into a constructor?
Problem 1 - Solution 2: Inject your container instead of creating a new one.
If you really need your controller for some reason, then you should try to inject it instead. This way you will get the same container as you used for your registrations.
public class MyApiController : ApiController
{
IUnityContainer _container;
public MyApiController(IUnityContainer container)
{
_container = container;
}
}
Problem 1 - Solution 3: Keep an static reference to your container.
As a last resort you can keep your container as a static instance.
public static class IocContainer
{
private static readonly Lazy<IUnityContainer> Container = new Lazy<IUnityContainer>(() =>
{
var container = new UnityContainer();
return container;
});
public static IUnityContainer Instance
{
get { return Container.Value; }
}
}
And in your registrations:
public static class UnityConfig
{
public static void RegisterComponents()
{
var container = IocContainer.Instance;
// register all your components with the container here
// it is NOT necessary to register your controllers
// e.g. container.RegisterType<ITestService, TestService>();
myContainer.RegisterType<IMasterDataClient, MasterDataClient>("MDS");
myContainer.RegisterType<ILinksManager, LinksManager>("LDS");
GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);
}
}
Usage:
IocContainer.Instance.Resolve<IMasterDataClient>("MDS");
Problem 2. You don't seem to register the dependencies for MasterDataClient.
It has dependencies for IApiClient and IUriDispenser. They need to be registered as well.
Problem 3. You assign your dependency resolver to the wrong container
You currently create two containers - myContainer and container. You make your registrations to one container, and then use another one as DependencyResolver. You can solve it by removing myContainer and only use container. Otherwise you will not be able to use your registrations in Web Api.
public static class UnityConfig
{
public static void RegisterComponents()
{
var container = new UnityContainer();
// register all your components with the container here
// it is NOT necessary to register your controllers
// e.g. container.RegisterType<ITestService, TestService>();
container.RegisterType<IMasterDataClient, MasterDataClient>("MDS");
container.RegisterType<ILinksManager, LinksManager>("LDS");
GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);
}
}
Update:
I don't know implementing classes for IApiClient and IUriDispenser as
it is third party dll so how can I register it
Unity needs to know which implementation to use when you resolve an interface. So somehow you need to tell Unity what implementation to use. There's an excellent answer from Mark Seemann in the question below:
Unity IoC for resolving assemblies dynamically
It scans the assembly for implementations of your interface and then registers them/it.
Alternatively you can use registration by convention, which enables you to do several registrations at once:
container.RegisterTypes(
AllClasses.FromLoadedAssemblies(),
WithMapping.MatchingInterface,
WithName.Default,
WithLifetime.ContainerControlled);
Note that this will register all implementations, including your own.
If you just want the third party implementations you should be able do do something like this:
// Get the assemblies where IApiClient exists.
IEnumerable<Assembly> assemblies = AppDomain.CurrentDomain.GetAssemblies()
.Where(x => x.GetTypes().Contains(typeof (IApiClient)));
// Register all implementations based on convention.
container.RegisterTypes(AllClasses.FromAssemblies(assemblies),
WithMappings.FromMatchingInterface,
WithName.Default,
WithLifetime.ContainerControlled); // Maybe another lifetime manager?
Update 2:
Make sure that the controller has a parameterless public constructor.
The error above can have many causes, most of them are covered in these questions:
Unable to inject DBContext into my Web API 2 Controller with Unity
Make sure that the controller has a parameterless public constructor error
error: Make sure that the controller has a parameterless public constructor webapi
Mostly it's Unity telling you that you're trying to resolve something that you didn't register. Or that you haven't registered a DependencyResolver at all.

Am I using correct lifetime managers for dependency injection?

I have an asp.net web api application that uses Unity dependency injection libraries from MS Unity.AspNet.WebApi and Unity nuget packages. Also, the application uses Entity Framework version 6 database context for ORM and a generic repository.
Custom service types are consumed by Api controllers. Custom Service classes consumes EF database contexts and the generic repository.
My question is: Are HierarchicalLifetimeManager and ContainerControlledLifetimeManager correct lifetime managers for my web api application?
Codes in the UnityConfig class of my application:
using System;
using System.Configuration;
using System.Data.Entity;
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.Configuration;
using App.Api.Models;
using App.Dal;
public class UnityConfig
{
#region Unity Container
private static Lazy<IUnityContainer> container = new Lazy<IUnityContainer>(() =>
{
var container = new UnityContainer();
RegisterTypes(container);
return container;
});
/// <summary>
/// Gets the configured Unity container.
/// </summary>
public static IUnityContainer GetConfiguredContainer()
{
return container.Value;
}
#endregion
/// <summary>Registers the type mappings with the Unity container.</summary>
/// <param name="container">The unity container to configure.</param>
/// <remarks>There is no need to register concrete types such as controllers or API controllers (unless you want to
/// change the defaults), as Unity allows resolving a concrete type even if it was not previously registered.</remarks>
public static void RegisterTypes(IUnityContainer container)
{
var connectionStringEntityFramework= ConfigurationManager.ConnectionStrings["AppEntities"].ToString();
// Entity Framework database context and generic repository
// HierarchicalLifetimeManager is used:
container.RegisterType<DbContext, FirstAngularJsEntities>(new HierarchicalLifetimeManager(), new InjectionConstructor(connectionStringFirstAngularJsEntities));
container.RegisterType<IRepository, GenRepository>(new HierarchicalLifetimeManager(), new InjectionConstructor(typeof(DbContext)));
// services
// ContainerControlledLifetimeManager is used:
container.RegisterType<IContactService, ContactService>(new ContainerControlledLifetimeManager());
container.RegisterType<IProductService, ProductService>(new ContainerControlledLifetimeManager());
}
A sample api controller has custom service injected in its constructor:
public class ContactApiController : ApiController
{
private readonly IContactService _contactService;
public ContactApiController(IContactService contactService)
{
_contactService = contactService;
}
...
}
A sample custom service has EF DbContext and repository injected in its constructor:
public class ContactService : IContactService
{
private readonly IRepository _repo;
private readonly DbContext _context;
public ContactService(DbContext context, IRepository repo)
{
_context = context;
_repo = repo;
}
...
}
Using ContainerControlledLifetimeManager you'll get singletons of your services. One instance for a long time (untill IIS recycling).
HierarchicalLifetimeManager is used with child containers - create new instance of object for every child container, so you don't create child containers it works like a singleton again :)
The best way for WebApi apllication is using PerRequestLifetimeManager.
Create new instances for every request to Api.
I tend to look at this as what is the shortest lifetime that is compatible with the semantics of what you are trying to do, with the default lifetime being Transient unless otherwise required.
DbContext holds state so we need to be consistent for the request so PerRequest or Hierachic
Repository is/should be stateless since it's state is the DbContext, so Transient
Services is/should be stateless so Transient
One reason for going with Hierarchic rather than PerRequest is that the PerRequest manager does not play well with Owin, see http://www.reply.com/solidsoft-reply/en/content/managing-object-lifetimes-with-owin-and-unity, and you will need to write some cleanup middleware to replace the HttpModule

Autofac Web Api Get current scope

I have the following extension method:
public static SessionUserInfo ToSessionUserInfo(this Customer customer)
{
//Some logic here which need some services
}
I'm using autofac with web api and owin, but because this is an extension method i cannot use Constructor injection. So i need to resolve the services from the logic in the code.
Normally using MVC and Autofac.Integration.MVC I would do something like that:
var scope = AutofacDependencyResolver.Current.RequestLifetimeScope;
MyService service = scope.Resolve<MyService>();
But I could not find a way to accomplish the same with Web API.
How can I do this in Web Api?
Unless you are using OWIN in your API, you should have your Autofac configuration setup in your WebAPI like this, which is the standard way to configure Autofac for WebApi.
Include nuget pacakge Autofac.Integration.WebApi
var builder = new ContainerBuilder();
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
builder.RegisterType<MyType>();
var container = builder.Build();
var resolver = new AutofacWebApiDependencyResolver(container);
GlobalConfiguration.Configuration.DependencyResolver = resolver;
Should you need to request the LifetimeScope like in your example, you can then request this from GlobalConfiguration.
var scope = GlobalConfiguration.Configuration.DependencyResolver.GetRequestLifetimeScope();
MyService service = scope.Resolve<MyService>();
Autofac WebApi configuration reference

How to use Autofac in seperate areas in mvc3?

I am now working on source code regarding ecommerce. In this source code , brnmall.web is the web project, its admin platform is in library brnmall.web.storeadmin which is registered in web project as area.
below is the brnmall.web:
below is the brnmall.web.storeadmin, registered as area in brnmall.web:
I want to use autofac in brnmall.web.storeadmin, so I add another global.asax in it, in the application_start method, I register all the controllers and components that I need.
but when I use the code below to trigger data
public ActionResult Index()
{
var serviceTypeRepo = unitOfWork.Repository<BrnMall.DAL.Access.cha_servicetype>();
var result = serviceTypeRepo.Get(x => x.serviceid == 1);
ViewBag.result = result;
return View();
}
exception throw to me: "An error occurred when trying to create a controller of type 'BrnMall.Web.Charging.Controllers.HomeController'. Make sure that the controller has a parameterless public constructor."
Anyone have the same scenario?
Is BrnMall.Web.StoreAdmin a seperate Web Application Project or an assembly project that is referenced by BrnMall.Web?
If StoreAdmin is just an Assembly referenced by BrnMall.Web and not a runnable Web Application on its own, then I believe you can remove the Seperate registrations and the global.asax in the StoreAdmin project, but I would replace these registrations with an AutofacModule registration class like below which will then register all your Controllers in that Assembly.
Then to wire it all up, you just need to have BrnMall.Web Autofac registration register your new module which will register Controllers in that assembly and any other components you decide to register there.
eg.
In your BrnMall.Web project....
public class Global : HttpApplication
{
private void Application_Start(object sender, EventArgs e)
{
var builder = new ContainerBuilder();
builder.RegisterControllers(Assembly.GetExecutingAssembly()); //Register controllers in the Executing Assembly
builder.RegisterModule<BrnMall.Web.StoreAdmin.AutofacModule>(); //Register the registrations in the StoreAdmin Autofac Module below.
//Register any other components
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
}
}
And in your BrnMall.Web.StoreAdmin ...
using Autofac;
public class AutofacModule : Module
{
protected override void Load(ContainerBuilder builder)
{
builder.RegisterControllers(ThisAssembly); //This will register any Controllers that are in this assembly
//Register any other components that relate to this particular Project
}
}
The benefit to registering Autofac Modules and referencing them is that you can specify in each project the registrations that belong to just that assembly which keeps the code a lot neater and all your registrations a lot neater.
I hope this helps?

MVC 3 Forms authentication with IOC container

I have a problem implementing forms authentication with an IOC container in my ASP.NET MVC 3 project. We have stored our user information in the database and has a lot of custom properties.
I have an interface of my user definition registrated to the IOC container for development purposes. This interface is given to each controller so the controllers has current user information.
This al works fine until i remove the dummy user registration in the Application_Start
I receive this error:
The current type, ...CurrentUserInformation.IUserInformation, is an interface and cannot be constructed. Are you missing a type mapping?
I don't want to work with a dummy user object because I think this is not the best practice.
Can sombody help me or is there a better way to do this custom authentication?
edit added some code
BaseController
public class BaseController : Controller
{
private readonly IUserInformation _userInformation;
public BaseController(IUserInformation userInformation)
{
_userInformation = userInformation
}
}
Bootstrapper Initialize called from Application_Start
public static void Initialise()
{
var container = BuildUnityContainer();
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}
private static IUnityContainer BuildUnityContainer()
{
var container = new UnityContainer();
//register all services en repositories
//here i put my dummy user wich i want to remove
container.RegisterInstance<IUserInformation>(
new UserInformation
{
UserId = 1,
...
});
return container;
}
You can use InjectionFactory:
container.RegisterType<IUserInformation, UserInformation>(
// User information is destroyed when the request ends.
// You could use an HttpSessionLifetimeManager as well, if it fits your needs
new HttpRequestLifetimeManager(),
new InjectionFactory(container => {
UserInformation userInfo = // TODO: build your userInformation from custom authentication
return userInfo;
}));

Resources