Dependency Injection in ASP.net Session_Start method - c#

I am learning dependency injection and using autofac for the first time. I built the container as mentioned in several autofac examples (see below) and called from my application_start
public class ContainerConfig
{
public static void RegisterContainer()
{
//Create a new ContainerBuilder
var builder = new ContainerBuilder();
// Register all the controllers using the assembly object
builder.RegisterControllers(Assembly.GetExecutingAssembly());
//Registering default convention -- IExample and Example
builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly())
.Where(t => t.Name.Single(i => i.Name == "I" + t.Name))
.AsImplementedInterfaces();
//Build the container
var container = builder.Build();
//Set the default resolver to use Autofac
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
}
}
I created UserService in my Core project with IUserService. This has methods to make dbcall to get user information from tables. In my UI project, i have a class called UserProvider to which i am tying to inject UserService.
public class UserProvider
{
private readonly IUserService _userService;
public UserProvider(IUserService userService)
{
_userService = userService;
}
public void LoadCurrentUser()
{
Users FoundUser = _userService.ImportOrGetUser();
if (FoundUser != null)
{
//add it to session
CurrentUser = FoundUser;
}
}
}
This UserProvider, i am using in my session_start
void Session_OnStart()
{
UserProvider OUsrPrv = new UserProvider(new UserService());
OUsrPrv.LoadCurrentUser();
}
In the above code, if i am passing 'new UserService()', my understanding is i am injecting UserService manually. I dont see how autofac is helping here. All the examples in google are talking about Dependency injection in MVCController or WebApiController, not in a individual class (UserProvider) like i am doing.
Can somebody please throw some light? Am I doing it all wrong?

In order to properly use Dependency Injection, you should never create instance by yourself, the underlying framework should provide instances for you.
But ASP.net invokes the Session_OnStart without any Dependency Injection. In this case you can use the DependencyResolver.Current static property to resolve the requested service.
void Session_OnStart()
{
UserProvider userProvider = DependencyResolver.Current.GetService<UserProvider>();
userProvider.LoadCurrentUser();
}

The event model in the System.Web.HttpApplication is part of ASP.NET, not MVC. It was not designed for use with dependency injection.
The answer that Cyril suggested is using a service locator to get a reference to the service. This is far from ideal, since you are taking on a dependency to the service locator in your code.
The MVC-centric way of implementing cross cutting concerns (such as loading user data into session state) is to use globally registered filters. You can either implement IAuthorizationFilter or IActionFilter to get the desired effect. In this case it makes sense to use IActionFilter since you want to wait until you are sure there is an authorized user before it is called.
NOTE: While this answers your specific question, it is best not to use session state for this scenario in MVC. An alternative is to use ASP.NET Identity with Claims to store user profile data instead of using Session.
using System;
using System.Web.Mvc;
using System.Security.Principal;
public class GetUserActionFilter : IActionFilter
{
private readonly IUserRepository userRepository;
public GetUserActionFilter(IUserRepository userRepository)
{
if (userRepository == null)
throw new ArgumentNullException("userRepository");
this.userRepository = userRepository;
}
public void OnActionExecuted(ActionExecutedContext filterContext)
{
// Do nothing - this occurs after the action method has run
}
public void OnActionExecuting(ActionExecutingContext filterContext)
{
IPrincipal user = filterContext.HttpContext.User;
if (user == null)
{
return;
}
IIdentity identity = user.Identity;
if (identity == null)
{
return;
}
// Make sure we have a valid identity and it is logged in.
if (identity.IsAuthenticated)
{
string key = "__CurrentUserData";
var userData = filterContext.HttpContext.Session[key];
if (userData == null)
{
// User data doesn't exist in session, so load it
userData = userRepository.GetUserData(identity.Name);
// Add it to session state
filterContext.HttpContext.Session[key] = userData;
}
}
}
}
Now, to add your filter globally, you need to:
Register the filter and its dependencies with Autofac.
Pass the container to the static RegisterGlobalFilters method.
Register the Filter
Using a named instance to differentiate it from other potential IActionFilter instances.
builder.RegisterType<GetUserActionFilter>()
.Named<IActionFilter>("getUserActionFilter");
Pass the Container
FilterConfig.cs
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters, IContainer container)
{
filters.Add(container.ResolveNamed<IActionFilter>("getUserActionFilter"));
filters.Add(new HandleErrorAttribute());
}
}
Global.asax.cs
public class MvcApplication : System.Web.HttpApplication
{
// This method serves as the composition root
// for the project.
protected void Application_Start()
{
// Register Autofac DI
IContainer container = ContainerConfig.RegisterContainer();
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters, container);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
AuthConfig.RegisterAuth();
}
}
ContainerConfig.cs
public class ContainerConfig
{
public static IContainer RegisterContainer()
{
//Create a new ContainerBuilder
var builder = new ContainerBuilder();
// Register all the controllers using the assembly object
builder.RegisterControllers(Assembly.GetExecutingAssembly());
//Registering default convention -- IExample and Example
builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly())
.Where(t => t.Name.Single(i => i.Name == "I" + t.Name))
.AsImplementedInterfaces();
// Register our filter
builder.RegisterType<GetUserActionFilter>()
.Named<IActionFilter>("getUserActionFilter");
//Build the container
var container = builder.Build();
//Set the default resolver to use Autofac
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
// Return the container to our composition root.
return container;
}
}
Note that I just used a repository service here, since HttpContext is available already through the action filter directly and additional logic is needed here because we don't know for sure if it exists in session state or not or whether there is even a user to lookup, so our filter does those checks in addition to loading session state.

Related

MVC with Castle Windsor RegisterForDispose

I have Castle Windsor Ioc in my MVC application. I have noticed that Objects tracked by release policy count is growing up all the time and as it seems this objects are never released(memory is growing up).
The code is:
public class ControllersInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(Classes.FromThisAssembly()
.BasedOn<IController>()
.LifestyleTransient());
}
}
In global.asax i have:
controllerFactory = new WindsorControllerFactory();
ControllerBuilder.Current.SetControllerFactory(controllerFactory);
controllerFactory.ValidateControllersResolution();
And class is:
public class WindsorControllerFactory: DefaultControllerFactory{
private readonly IWindsorContainer container;
public WindsorControllerFactory()
{
container = new WindsorContainer()
.Install(FromAssembly.This())
.AddFacility<WcfFacility>();
default policy is: LifecycledComponentsReleasePolicy
//container.Kernel.ReleasePolicy;
}
public override void ReleaseController(IController controller)
{
//this is called after each view return
container.Kernel.ReleaseComponent(controller);
}
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
if (controllerType == null)
{
throw new HttpException(404,
$"The controller for path '{requestContext.HttpContext.Request.Path}' could not be found.");
}
var controller= ((IController)container.Kernel.Resolve(controllerType)).AddControllerLoggingFunctionality();
return controller;
}
public void DisposeContainer()
{//this is never executed
container.Dispose();
}
In WEB API version: Web API with Castle Windsor
there is register for dispose before returning controller:
request.RegisterForDispose(
new Release(
() => this.container.Release(controller)));
But in my case there is RequestContext instead of HttpRequestMessage, which doesn't have RegisterForDispose method. Is there some other way to register for dispose or some other way to dispose controller after view is returned?
Or I'm not on the right track?
The RegisterForDispose() method only exists on HttpRequestMessage because it is capable of associating arbitrary objects with the request for the duration of the request through its Properties collection. Even the framework itself uses it (in GetOwinContext(), for example).
On the other hand, the traditional HttpRequest (that is available for MVC controllers) does not expose this capability* hence no RegisterForDispose() is provided.
* (Although you can associate arbitrary items to the HttpContext.Items, that is generally used to pass data between modules. If you were to use it to associate items to the current request, you'll have to dispose them manually as well

Autofac: How to inject IPrincipal into Repository layer

I am designing an n-tier application using Repository Layer/Service Layer/Presentation Layer using c#.net web api and Autofac DI container. Here is my dilemma. I am trying to unit test my web api controllers but my repositories have a property dependency on IPrincipal which I would like to property inject into my repository layer. I would like to create a MockUser(IPrincipal) and inject this object into my repository. Here is my current hierarchy, my controllers are constructor injected with the service object, my service object is constructor injected with my repository object. This part seems to work. But for some reason, every time I run the test my Principal property is null. Please review the code below and let me know what I am doing wrong:
Repository Base Class:
protected IPrincipal Principal
{
get { return _principal; }
}
Autofac Config Static Method
public class AutofacConfig
{
public static IContainer ConfigContainer()
{
var _builder = new ContainerBuilder();
UserPrincipal principal = MemberFactory.GetTestUser();
var _config = new HttpConfiguration();
_builder.RegisterControllers(typeof(BillingController).Assembly);
_builder.RegisterWebApiModelBinders(typeof(BillingController).Assembly);
_builder.RegisterApiControllers(typeof(BillingController).Assembly);
_builder.RegisterModelBinders(typeof(BillingController).Assembly);
_builder.RegisterModelBinderProvider();
_builder.RegisterModule(new AutofacWebTypesModule());
_builder.RegisterSource(new ViewRegistrationSource());
_builder.RegisterFilterProvider();
_builder.RegisterWebApiFilterProvider(_config);
//_builder.Register(x => principal).As<IPrincipal>().PropertiesAutowired();
_builder.RegisterType<BillingRepository>().As<IBillingRepository>().PropertiesAutowired();
_builder.RegisterType<UserPrincipal>().As<IPrincipal>().PropertiesAutowired();
_builder.RegisterType<GroupRepository>().As<IGroupRepository>().PropertiesAutowired();
_builder.RegisterType<BillingService>().As<IBillingService>().PropertiesAutowired();
_builder.RegisterType<UnitOfWork>().As<IUnitOfWork>();
_builder.Register(c => principal).As<IPrincipal>();
var _container = _builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(_container));
// Create the depenedency resolver.
var resolver = new AutofacWebApiDependencyResolver(_container);
// Configure Web API with the dependency resolver.
_config.DependencyResolver = resolver;
return _container;
}
}
Test Controller (Get Method)
[TestClass]
public class BillingControllerTest
{
[TestMethod]
public async Task Get()
{
var _container = AutofacConfig.ConfigContainer();
var _controller = _container.Resolve<BillingController>();
var _bodyCompRecords = await _controller.GetMyOutstandingBills(1, 10);
Assert.IsNull(_bodyCompRecords);
Assert.IsNull(_bodyCompRecords.BillingList);
Assert.IsNull(_bodyCompRecords.CurrentPage);
Assert.IsTrue(_bodyCompRecords.BillingList.Count > 0);
}
}
Did you try to add a protected set for this property? I am not sure about autofac but maybe you should decorate this property with some attribute to autoFac knows that is a injectable property.
On the other hand, all threads in .Net applications has a single principal. You can get/set it on the Thread.CurrentPrincipal static property. You could try to set a custom Principal and make your property to result it.
In the setup of your Unittest, you could define it, for sample:
void Setup()
{
IPrincipal principal = new GenericPrincipal(new GenericIdentity("userName"), new string[] { "role1", "role2" });
Thread.CurrentPrincipal = principal;
}
In your repository, you could have a property to expose it,
protected IPrincipal Principal
{
get { return Thread.CurrentPrincipal; }
}
In a Web application (asp.net webforms/mvc/web api), you could use the HttpContext.Current.User static property, so, just call:
HttpContext.Current.User = principal;
as a good pratice, you could set both HttpContext.Current.User and Thread.CurrentPrincipal. Remember the web api is stateless, so, implement a http module to read arguments from http header and set the principal to your application. I am not sure if it is your case but this article shows how to do this.
http://www.asp.net/web-api/overview/security/basic-authentication

Child container registration based on route parameters

We have a multi-tennant ASP.NET MVC application that hosts a booking engine for multiple clients. Each of these clients has multiple packages that can influence Unity Container configuration. We are creating a child container per request and registering different interface implementations based on the client and package parameters passed through the route.
Currently we are accomplishing this by doing the following:
Controller has a property ServiceLocator that uses a unity container to resolve dependencies.
Controller gets IUnityContainer injected and assigned to a property.
Controller has a custom ActionFilterAttribute that accesses the controllers unity container, creates a child container, conditionally registers dependency implementations based on client and package route parameters, then assigns this child container to the controller's serviceLocator.
Controller uses serviceLocator on demand to resolve individual dependencies.
This works but is really clumsy and I feel eventually it will be unsustainable. I'm looking for a better solution.
We're stuck on .NET 4.0 at the moment until we wrap up some legacy stuff so I'm targeting Unity 2 specifically.
I've tried creating a custom IDependencyResolver to create the child container and register dependencies based on route parameters storing the container in either Session or in HttpContext items but ran into the null HttpContext problems. Is there any other way to base registrations on the route and have the dependencies injected to the controller constructor?
Eventually I will need a solution for Web API as well.
Edit: Example
public interface IRateService { ... }
public class RemoteRateService : IRateService { ... }
public class LocalRateService : IRateService { ... }
public class CustomDependencyResolver : IDependencyResolver
{
public object GetService(Type serviceType)
{
if(ChildContainer == null)
{
ChildContainer = _container.CreateChildContainer();
var routeData = HttpContext.Current.Request.RequestContext.RouteData.Values;
if(routeData["client"] == "ClientA")
ChildContainer.RegisterType<IRateService, RemoteRateService>();
else
ChildContainer.RegisterType<IRateService, LocalRateService>();
}
return ChildContainer.Resolve(serviceType);
}
}
public class RateController : Controller
{
private IRateService _rateService;
public RateController(IRateService rateService)
{
_rateService = rateService;
}
...
}
url: /ClientA/Package1/Rate - RateController gets RemoteRateService
url: /ClientB/Package2/Rate - RateController gets LocalRateService
Abatishchev answered my question in the comments by pointing me in the right direction with IControllerFactory. For the random google searches that end here, here is the basic setup I used by inheriting from DefaultControllerFactory:
public class UnitySessionControllerFactory : DefaultControllerFactory
{
private const string HttpContextKey = "Container";
private readonly IUnityContainer _container;
public UnitySessionControllerFactory (IUnityContainer container)
{
_container = container;
}
protected IUnityContainer GetChildContainer(RequestContext requestContext)
{
var routeData = requestContext.RouteData.Values
?? new RouteValueDictionary();
var clientName = routeData["clientName"] as string;
var packageId = routeData["packageID"] as int?;
if (clientName == null)
throw new ArgumentException("ClientName not included in route parameters");
var childContainer = requestContext.HttpContext.Session[clientName + HttpContextKey] as IUnityContainer;
if (childContainer != null)
return childContainer;
requestContext.HttpContext.Session[clientName + HttpContextKey] = childContainer = _container.CreateChildContainer();
var moduleLoader = childContainer.Resolve<ModuleLoader>();
moduleLoader.LoadModules(clientName, packageId);
return childContainer;
}
public override IController CreateController(RequestContext requestContext, string controllerName)
{
var controllerType = GetControllerType(requestContext, controllerName);
var container = GetChildContainer(requestContext);
return container.Resolve(controllerType) as IController;
}
public override void ReleaseController(IController controller)
{
_container.Teardown(controller);
}
}
Forgive the use of session here. In the future I will exchange it for HttpContext.Items once I am able to wrangle in our project's use of session.
To enable the custom controller factory I added this line to the Bootstrapper.Initialise() method
ControllerBuilder.Current
.SetControllerFactory(new UnitySessionControllerFactory(container));

Avoiding Service Locator Antipattern with HTTP Request Lifetime Scope and Global Filter

I have a global filter attribute that needs access to an item that is registerd per HTTP request:
// other ContainerBuilder stuff
builder.RegisterType<HttpDependency>().As<IHttpDependency>().InstancePerHttpRequest();
And elsewhere:
internal sealed class MyActionFilter : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
// EVIL YUCKY SERVICE LOCATOR!
var resolved = AutofacDependencyResolver.Current.RequestLifetimeScope.Resolve<IHttpDependency>();
if (resolved.NeedsRedirect)
{
// does a redirect
}
base.OnActionExecuting(filterContext);
}
}
And registering it as a global filter:
// in FilterConfig.cs
filters.Add(new MyActionFilter());
Since this is a global filter, I can't use constructor injection, i.e. the HTTP context on app startup shouldn't get reused for every request. How can I wire this up properly without resorting to reaching out and grabbing it via a service locator?
One method is to remove your logic from the Attribute and implement it in a class that implements IActionFilter. The class is then registered with the container so that dependency injection will work correctly. Orchard CMS using this approach.
public class MyCustomActionFilterAttribute : Attribute
{
}
public class MyCustomActionFilter : FilterProvider, IActionFilter
{
protected MyService Service { get; private set; }
// MyService can be injected by the container...
public MyCustomActionFilter(MyService service)
{
this.Service = service;
}
public void OnActionExecuted(ActionExecutedContext filterContext)
{
// Check to see if the action has a matching attribute
var attributes = filterContext.ActionDescriptor.GetCustomAttributes(typeof(MyCustomActionFilterAttribute), true);
// Perform some logic here....
}
public void OnActionExecuting(ActionExecutingContext filterContext)
{
}
}
It is possible to create an IActionInvoker that applies the filter to the action, this class is automatically instantiated my MVC using the DependencyResolver.
public class FilterResolvingActionInvoker : ControllerActionInvoker
{
protected IEnumerable<IFilterProvider> Providers { get; private set; }
// Filters registered with the container are injected by the container
public FilterResolvingActionInvoker(IEnumerable<IFilterProvider> providers)
{
this.Providers = providers;
}
// Add the filter to the current FilterInfo
protected override FilterInfo GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
{
var filters = base.GetFilters(controllerContext, actionDescriptor);
foreach (var provider in this.Providers)
{
provider.AddFilters(filters);
}
return filters;
}
}
Define a common interface that allows us to register our filters.
public interface IFilterProvider
{
void AddFilters(FilterInfo filterInfo);
}
public abstract class FilterProvider : IFilterProvider
{
public void AddFilters(FilterInfo filterInfo)
{
if (this is IActionFilter)
{
filterInfo.ActionFilters.Add(this as IActionFilter);
}
}
}
And register them with the container builder. It is also possible to create an extension method for Autofac to automatically register all IFilterProviders in your assembly.
builder.RegisterType<FilterResolvingActionInvoker>().As<IActionInvoker>().InstancePerDependency();
builder.RegisterType<MyCustomActionFilter>().As<IFilterProvider>().InstancePerDependency();
As always, one of the options to avoid the locator is to have a local factory which is set up in the Compositon Root. The factory is set up so that it uses your ioc container.
http://netpl.blogspot.com/2012/12/di-factories-and-composition-root.html
Although you could argue that "technically" this "looks like" locator (you create a factory instance and ask it for the service), it doesn't introduce any dependencies to any other infrastructure including the actual IoC container you ultimately use to implement the factory - the implementation of the actual factory is a part of the Composition Root (somewhere near the global application class).
Such approach leads to a lot of isolated small factories responsible for parts of your infrastructure but still each factory has a pluggable provider you can implement near the Composition Root thus avoiding any external dependencies.

Exception is: InvalidOperationException - The current type, is an interface and cannot be constructed. Are you missing a type mapping?

In my bootstrapper:
namespace Conduit.Mam.ClientServices.Common.Initizliaer
{
public static class Initializer
{
private static bool isInitialize;
private static readonly object LockObj = new object();
private static IUnityContainer defaultContainer = new UnityContainer();
static Initializer()
{
Initialize();
}
public static void Initialize()
{
if (isInitialize)
return;
lock (LockObj)
{
IUnityContainer container = defaultContainer;
//registering Unity for MVC
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
//registering Unity for web API
// GlobalConfiguration.Configuration.DependencyResolver = new Unity.WebApi.UnityDependencyResolver(container);
#region managers
container.RegisterType<ISettingsManager, SettingsManager>();
container.RegisterType<IMamDataManager, MamDataManager>();
container.RegisterType<IAppsDataManager, AppsDataManager>();
#endregion
if (!isInitialize)
{
isInitialize = true;
}
}
}
}
}
in my controller's code:
ISettingsManager sm = mUnityContainer.Resolve<ISettingsManager>();
hovering on mUnityContainer I see ISettingsManager is mapped to SettingsManager
but then I get the error:
Exception is: InvalidOperationException - The current type, is an
interface and cannot be constructed. Are you missing a type mapping?
I have also tried
ISettingsManager sm = (ISettingsManager)mUnityContainer.Resolve<>(typeof(ISettingsManager));
but no use
Just for others (like me) who might have faced the above error. The solution in simple terms.
You might have missed to register your Interface and class (which implements that inteface) registration in your code.
e.g if the error is
"The current type, xyznamespace. Imyinterfacename, is an interface and cannot be constructed. Are you missing a type mapping?"
Then you must register the class which implements the Imyinterfacename in the UnityConfig class in the Register method. using code like below
container.RegisterType<Imyinterfacename, myinterfaceimplclassname>();
You are incorrectly using Dependency Injection. The proper way is to have your controllers take the dependencies they need and leave to the dependency injection framework inject the concrete instances:
public class HomeController: Controller
{
private readonly ISettingsManager settingsManager;
public HomeController(ISettingsManager settingsManager)
{
this.settingsManager = settingsManager;
}
public ActionResult Index()
{
// you could use the this.settingsManager here
}
}
As you can see in this example the controller doesn't know anything about the container. And that's how it should be.
All the DI wiring should happen in your Bootstraper. You should never use container.Resolve<> calls in your code.
As far as your error is concerned, probably the mUnityContainer you are using inside your controller is not the same instance as the one constructed in your Bootstraper. But since you shouldn't be using any container code in your controllers, this shouldn't be a problem anymore.
In my case, I was getting this error despite registering an existing instance for the interface in question.
Turned out, it was because I was using Unity in WebForms by way of the Unity.WebForms Nuget package, and I had specified a Hierarchical Lifetime manager for the dependency I was providing an instance for, yet a Transient lifetime manager for a subsequent type that depended on the previous type - not usually an issue - but with Unity.WebForms, the lifetime managers work a little differently... your injected types seem to require a Hierarchical lifetime manager, but a new container is still created for every web request (because of the architecture of web forms I guess) as explained excellently in this post.
Anyway, I resolved it by simply not specifying a lifetime manager for the types/instances when registering them.
i.e.
container.RegisterInstance<IMapper>(MappingConfig.GetMapper(), new HierarchicalLifetimeManager());
container.RegisterType<IUserContext, UserContext>(new TransientLifetimeManager());
becomes
container.RegisterInstance<IMapper>(MappingConfig.GetMapper());
container.RegisterType<IUserContext, UserContext>();
So that IMapper can be resolved successfully here:
public class UserContext : BaseContext, IUserContext
{
public UserContext(IMapper _mapper) : base(_mapper)
{
}
...
}
In my case, I have used 2 different context with Unitofwork and Ioc container so i see this problem insistanting while service layer try to make inject second repository to DI. The reason is that exist module has containing other module instance and container supposed to gettng a call from not constractured new repository.. i write here for whome in my shooes
May be You are not registering the Controllers.
Try below code:
Step 1.
Write your own controller factory class
ControllerFactory :DefaultControllerFactory by implementing defaultcontrollerfactory
in models folder
public class ControllerFactory :DefaultControllerFactory
{
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
try
{
if (controllerType == null)
throw new ArgumentNullException("controllerType");
if (!typeof(IController).IsAssignableFrom(controllerType))
throw new ArgumentException(string.Format(
"Type requested is not a controller: {0}",
controllerType.Name),
"controllerType");
return MvcUnityContainer.Container.Resolve(controllerType) as IController;
}
catch
{
return null;
}
}
public static class MvcUnityContainer
{
public static UnityContainer Container { get; set; }
}
}
Step 2:Regigster it in BootStrap:
inBuildUnityContainer method
private static IUnityContainer BuildUnityContainer()
{
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>();
//RegisterTypes(container);
container = new UnityContainer();
container.RegisterType<IProductRepository, ProductRepository>();
MvcUnityContainer.Container = container;
return container;
}
Step 3:
In Global Asax.
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
AuthConfig.RegisterAuth();
Bootstrapper.Initialise();
ControllerBuilder.Current.SetControllerFactory(typeof(ControllerFactory));
}
And you are done
I had this problem, and the cause was that I had not added the Microsoft.Owin.Host.SystemWeb NuGet package to my project. Although the code in my startup class was correct, it was not being executed.
So if you're trying to solve this problem, put a breakpoint in the code where you do the Unity registrations. If you don't hit it, your dependency injection isn't going to work.
Below code will be helpful for you
public static IUnityContainer Initialise(IUnityContainer container = null)
{
if (container == null)
{
container = new UnityContainer();
}
container.RegisterType<ISettingsManager, SettingsManager>();
container.Resolve<SettingsManager>();
container.RegisterType<SettingsManagerController>(new InjectionProperty("_SettingManagerProvider", new ResolvedParameter<ISettingManager>()));
return container;
}

Categories