I used the following to learn DI and its use inside the MVC application
http://www.c-sharpcorner.com/UploadFile/dacca2/implement-ioc-using-unity-in-mvc-5/
NuGet packages referenced in this article for unity, built the whole code for me and placed it inside the app_start folder. I created my interface and implemented it on a class, created the definition in the bootstrapper (UnityConfig class).
#1:
Then i placed the following in my controller and i was able to get the information (static string) from my class method without any issue:
[Dependency] public ISomeThing SomeThingInstance { get; set; }
#2:
Now, i took this one step further since a good project should be built in layers, every thing shouldn't be in the web application.
I created a new project "Core" in the solution and moved the DI code from app_start to here.
Then created a "Repository" project with two folders "Services" and "Services Interfaces" and moved my ISomeThing interface and SomeThing class here.
Just like #1 example, i was able to use it without any issue in my controller.
#3:
Then i took this one step further, and created a MVCBase Project. Put one HelperClass in there -- like in theory this project will house filters, extensions etc..
Now when i use the following in this HelperClass, i get an exception of type 'System.NullReferenceException' occurred in Unity.Test2.MvcBase.dll but was not handled in user code. Additional information: Object reference not set to an instance of an object.
namespace Unity.Test2.MvcBase.Helper { public class DataHelper { [Dependency] public ISomeThing SomeThingInstance { get; set; } public string GetSomthing() { return SomeThingInstance.ReturnedViaHelperclass(); //ERROR IS HERE } } }
I was only able to create the object by doing following in the HelperClass - adding constructor method and then resolving the dependency manually.
namespace Unity.Test2.MvcBase.Helper { public class DataHelper { //[Dependency] //public ISomeThing SomeThingInstance { get; set; } private ISomeThing SomeThingInstance {get; set;} public DataHelper() { var container = UnityConfig.GetConfiguredContainer(); SomeThingInstance = container.Resolve<ISomeThing>(); } public string GetSomthing() { return SomeThingInstance.ReturnedViaHelperclass(); } } }
Here is the controller code
namespace Unity.Test2.Controllers { public class HomeController : Controller { [Dependency] public ISomeThing SomeThingInstance { get; set; } // GET: Home public ActionResult Index() { var model = new HomeIndexViewModel(); model.Normal = SomeThingInstance.SomeThingGet(); model.ViaDataHelper = new DataHelper().GetSomthing(); return View(model); } } }
Here is the unity config code created by the nuget package
namespace Unity.Test2.MvcBase.App_Start { /// <summary> /// Specifies the Unity configuration for the main container. /// </summary> 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) { // NOTE: To load from web.config uncomment the line below. Make sure to add a Microsoft.Practices.Unity.Configuration to the using statements. // container.LoadConfiguration(); // TODO: Register your types here container.RegisterType<ISomeThing, SomeThing>(); } } }
and unity mvc activator class code created by nuget package
[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(Unity.Test2.MvcBase.App_Start.UnityWebActivator), "Start")] [assembly: WebActivatorEx.ApplicationShutdownMethod(typeof(Unity.Test2.MvcBase.App_Start.UnityWebActivator), "Shutdown")] namespace Unity.Test2.MvcBase.App_Start { /// <summary>Provides the bootstrapping for integrating Unity with ASP.NET MVC.</summary> public static class UnityWebActivator { /// <summary>Integrates Unity when the application starts.</summary> public static void Start() { var container = UnityConfig.GetConfiguredContainer(); FilterProviders.Providers.Remove(FilterProviders.Providers.OfType<FilterAttributeFilterProvider>().First()); FilterProviders.Providers.Add(new UnityFilterAttributeFilterProvider(container)); DependencyResolver.SetResolver(new UnityDependencyResolver(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() { var container = UnityConfig.GetConfiguredContainer(); container.Dispose(); } } }
Now, in case of #3, why do it need to resolve the dependency manually? Why can't i use it just like i have it in the controller? Am I missing something here?