This posts explains how to set up an MVC5 application using Unity 3 and Semantic Logging (SLAB). Attribute Routing is used for the controllers.
Code: https://github.com/damienbod/MVC5UnitySlab
Adding Unity 3 to the MVC5 project
Add the NuGet packages to the MVC5 project.
Now add the start up logic in the UnityConfig file in the App_Start folder.
using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using Microsoft.Practices.Unity; using MVC5UnitySlab.Business.Attributes; namespace MVC5UnitySlab.App_Start { /// <summary> /// Specifies the Unity configuration for the main container. /// </summary> public class UnityConfig { private const string ClassesToScan = "MVC5UnitySlab"; #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 public static IEnumerable<Type> GetTypesWithCustomAttribute<T>(Assembly[] assemblies) { foreach (var assembly in assemblies) { foreach (Type type in assembly.GetTypes()) { if (type.GetCustomAttributes(typeof(T), true).Length > 0) { yield return type; } } } } /// <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 myAssemblies = AppDomain.CurrentDomain.GetAssemblies() .Where(a => a.FullName.StartsWith(ClassesToScan)) .ToArray(); container.RegisterTypes( UnityConfig.GetTypesWithCustomAttribute<UnityIoCContainerControlledAttribute>(myAssemblies), WithMappings.FromMatchingInterface, WithName.Default, WithLifetime.ContainerControlled, null ).RegisterTypes( UnityConfig.GetTypesWithCustomAttribute<UnityIoCTransientLifetimeAttribute>(myAssemblies), WithMappings.FromMatchingInterface, WithName.Default, WithLifetime.Transient); } } }
This start up configuration uses a scan method to search for interfaces and classes to be registered with unity. The scan method uses attributes to define the lifetime of each class.
namespace MVC5UnitySlab.Business.Attributes { [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct)] public class UnityIoCContainerControlledAttribute : System.Attribute { public double version; public UnityIoCContainerControlledAttribute() { version = 1.0; } } }
These attributes are applied to the different classes which are to be registered with the IoC.
[UnityIoCTransientLifetime] public class BusinessClass : IBusinessClass { private IUnitOfWorkExample _unitOfWorkExample; public BusinessClass(IUnitOfWorkExample unitOfWorkExample) { _unitOfWorkExample = unitOfWorkExample; UnityEventLogger.Log.CreateUnityMessage("BusinessClass"); }
Now the business classes can be used in any controller.
public class HomeController : Controller { private IBusinessClass2 _businessClass2; private IBusinessClass _businessClass; public HomeController(IBusinessClass2 businessClass2, IBusinessClass businessClass) { _businessClass = businessClass; _businessClass2 = businessClass2; } public ActionResult Index() { _businessClass.Hello(); _businessClass2.Hello(); _businessClass2.SayHello("using unity happily"); return View(); }
Using Out-Of-Process Semantic Logging (SLAB)
Add the Semantic logging NuGet package to the MVC5 project.
Add an EventSource class and write some logs.
using System.Diagnostics.Tracing; namespace MVC5UnitySlab.Business.Logging { [EventSource(Name = "UnityLogger")] public class UnityEventLogger : EventSource { public static readonly UnityEventLogger Log = new UnityEventLogger(); private const int createUnityMessageEventId = 1; private const int disposeUnityMessageEventId = 2; private const int logUnityMessageEventId = 3; [Event(createUnityMessageEventId, Message = "CreateUnityMessage: {0}", Level = EventLevel.Informational)] public void CreateUnityMessage(string message) { if (IsEnabled()) WriteEvent(createUnityMessageEventId, message); } [Event(disposeUnityMessageEventId, Message = "DisposeUnityMessage {0}", Level = EventLevel.Informational)] public void DisposeUnityMessage(string message) { if (IsEnabled()) WriteEvent(disposeUnityMessageEventId, message); } [Event(logUnityMessageEventId, Message = "{0}", Level = EventLevel.Informational)] public void LogUnityMessage(string message) { if (IsEnabled()) WriteEvent(logUnityMessageEventId, message); } } }
Here’s a log example.
UnityEventLogger.Log.CreateUnityMessage("BusinessClass2");
Install the Semantic Logging OUT-OF-PROCESS service and add your logs to the xml see Enterprise Library 6, Semantic Logging, Part 2, OUT-OF-PROCESS
Edit the SemanticLogging-svc.xml as required.
<sqlDatabaseSink name="myDb" instanceName="UnityCreateDisposeTest" connectionString="Data Source=.;Initial Catalog=Logging;Integrated Security=True"> <sources> <eventSource name="UnityLogger" level="LogAlways"/> </sources> </sqlDatabaseSink>
Here’s a database sink result:
Using Attribute Routing
Change the RouteConfig class in the App_Start folder. Add the MapMvcAttributeRoutes method and remove the old routing.
using System.Web.Mvc; using System.Web.Routing; namespace MVC5UnitySlab { public class RouteConfig { public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapMvcAttributeRoutes(); } } }
Add the routing attributes to the controller as required:
[RoutePrefix("MyHome")] public class HomeController : Controller { private IBusinessClass2 _businessClass2; private IBusinessClass _businessClass; public HomeController(IBusinessClass2 businessClass2, IBusinessClass businessClass) { _businessClass = businessClass; _businessClass2 = businessClass2; } [Route("{Index}")] public ActionResult Index() { _businessClass.Hello(); _businessClass2.Hello(); _businessClass2.SayHello("using unity happily"); return View(); }
This routing is then used:
Links:
http://www.asp.net/mvc/tutorials/mvc-5
http://blogs.msdn.com/b/webdev/archive/2013/10/17/attribute-routing-in-asp-net-mvc-5.aspx
http://sampathloku.blogspot.ch/2013/11/attribute-routing-with-aspnet-mvc-5.html
Reblogged this on Crazy Developer.
UnityIoCTransientLifetimeAttribute is not defined
This is defined in the business assembly. For large projects, I define these attributes in a common utility class.
https://github.com/damienbod/MVC5UnitySlab/blob/master/MVC5UnitySlab.Business/Attributes/UnityIoCTransientLifetimeAttribute.cs
greetings Damien
Thanks damienbod for this article, I found below blog post about Unity.Mvc5 Library example with sample code.
MVC 5 with Unity for Dependency Injection