Search

Categories

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Send mail to the author(s) E-mail

# Tuesday, 21 January 2014
( IoC )

Why IoC rather than Constructor based DI?

  • Ease of testing
  • Less code
  • Promoting decoupling

Added Unity via Nuget.  Wired up global.asax, and UnityConfig.

image
When doing authentication.

container.RegisterType<AccountController>(new InjectionConstructor());

In UnityConfig.cs

| | # 
( IoC )

    public class ProteinRepository : IProteinRepository
    {
        private readonly string dataSource;

        public ProteinRepository(string dataSource)
        {
            this.dataSource = dataSource;
        }

Container is automatically trying to create ProteinRepository for us, but doesn’t know what to give it.

image

public static class UnityConfig
{
    public static void RegisterComponents()
    {
        var container = new UnityContainer();
            
        // it is NOT necessary to register your controllers
        container.RegisterTypes(
            AllClasses.FromLoadedAssemblies(),
            WithMappings.FromMatchingInterface, // Convention of an I in front of interface name
            WithName.Default
            );  // Default not a singleton in Unity

        // could put in string from web.config here
        container.RegisterType<IProteinRepository, ProteinRepository>(new InjectionConstructor("test data source"));

        DependencyResolver.SetResolver(new UnityDependencyResolver(container));
    }
}

Named registrations is another way of switching out eg between debug and release.

Try to confine classes to 1 or 2 dependencies.

| | # 
( IoC )

image

Can use constructor injection here.

Going to apply a filter which will apply to all actions.  Which will have a dependency

 

image
Top of every page now is output from DebugService.

namespace MvcIoC
{
    public class FilterConfig
    {
        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            filters.Add(new HandleErrorAttribute());
            // Resolving a concrete type.. which has dependencies, which will be resolved
            filters.Add(DependencyResolver.Current.GetService<DebugFilter>());
        }
    }
}
public class DebugFilter : ActionFilterAttribute
{
    private IDebugMessageService debugMessageService;

    public DebugFilter(IDebugMessageService debugMessageService)
    {
        this.debugMessageService = debugMessageService;
    }

    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        filterContext.HttpContext.Response.Write(debugMessageService.Message);
    }
}
    public class DebugMessageService : IDebugMessageService
    {
        public string Message
        {
            get
            {
                return DateTime.Now.ToString();
            }
        }
    }

Good way of logging, security

| | # 
( IoC )

image

Analytics tracking in the view..ie what users are clicking on in view

Because of restriction that pages have to have a parameterless constructor we have to do things this way..

    public class ProteinTrackerBasePage : WebViewPage
    {
        [Dependency]
        public IAnalyticsService AnalyticsService { get; set; }

        public override void Execute()
        {

        }
    }

    public class AnalyticsService : IAnalyticsService
    {
        public string Code
        {
            get { return "Tracking you!"; }
        }
    }

image
Why?  Almost like codebehind..  Injecting Services into a View.. eg localization, format provider

| | # 
( IoC | Unity )

image

 

image

MVC Uses a Static Dependency Resolver.. to resolve all of its dependencies.  ie MVC will use our implementation.

Unity allows for

  • Constructor based injection (like we’ve used)
  • Property
  • Method

Can setup dependencies using

  • Code
  • Configuration (ie change without recompile)
  • Convention

Can use decorator pattern for more AOP.  And lifetime management eg singleton instance easily.

image
Going to include a bootstrapper class which makes things easier.

Looks like Unity.MVC5 doesn’t need to bootstrap file like in MVC4

        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            UnityConfig.RegisterComponents();  

            WebApiConfig.Register(GlobalConfiguration.Configuration);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
            AuthConfig.RegisterAuth();

            //var factory = new CustomControllerFactory();
            //ControllerBuilder.Current.SetControllerFactory(factory);
        }

which points to.. Ahh, Initialise in bootstrapper is just like the 2 lines below.

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>();
            
        DependencyResolver.SetResolver(new UnityDependencyResolver(container));
    }
}
image

Can see we are using Unity, but cant find the type. ie there is no registration!

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<IProteinTrackingService, ProteinTrackingService>();
    container.RegisterType<IProteinRepository, ProteinRepository>();

    DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}

Repetitive mapping code.. can use convention

public static void RegisterComponents()
{
    var container = new UnityContainer();
            
    // it is NOT necessary to register your controllers
    container.RegisterTypes(
        AllClasses.FromLoadedAssemblies(),
        WithMappings.FromMatchingInterface, // Convention of an I in front of interface name
        WithName.Default
        );  // Default not a singleton in Unity

    DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}
| | # 
( IoC )

/dev/test/MvcIoC.sln

image

    public class ProteinTrackingService
    {
        private ProteinRepository repository = new ProteinRepository();

        public int Total
        {
            get { return repository.GetData(new DateTime().Date).Total; }
            set { repository.SetTotal(new DateTime().Date, value); }
        }

        public int Goal
        {
            get { return repository.GetData(new DateTime().Date).Goal; }
            set { repository.SetGoal(new DateTime().Date, value); }
        }

        public void AddProtein(int amount)
        {
            Total += amount;
        }
    }

 

    public interface IProteinRepository
    {
        ProteinData GetData(DateTime date);
        void SetTotal(DateTime date, int value);
        void SetGoal(DateTime date, int value);
    }

    public class ProteinRepository : IProteinRepository
    {
        private static ProteinData data = new ProteinData();
        public ProteinData GetData(DateTime date)
        {
            return data;
        }

        public void SetTotal(DateTime date, int value)
        {
            data.Total = value;
        }

        public void SetGoal(DateTime date, int value)
        {
            data.Goal = value;
        }
    }

    public class ProteinData
    {
        public int Total { get; set; }
        public int Goal { get; set; }
    }

looking at the project..37secs in.

image

public class ProteinTrackerController : Controller
    {
        private readonly IProteinTrackingService proteinTrackingService;

        public ProteinTrackerController(IProteinTrackingService proteinTrackingService)
        {
            this.proteinTrackingService = proteinTrackingService;
        }

        public ActionResult Index()
        {
            ViewBag.Total = proteinTrackingService.Total;
            ViewBag.Goal = proteinTrackingService.Goal;

            return View();
        }

Now app wont run as need a parameterless constructor.  Rather than hack one one, he is going to build his own CustomControllerFactory off IControllerFactory

public class CustomControllerFactory : IControllerFactory
{
    public IController CreateController(RequestContext requestContext, string controllerName)
    {
        if (controllerName.ToLower().StartsWith("proteintracker"))
        {
            var service = new ProteinTrackingService();
            var controller = new ProteinTrackerController(service);
            return controller;
        }

        var defaultFactory = new DefaultControllerFactory();
        return defaultFactory.CreateController(requestContext, controllerName);
    }

    public SessionStateBehavior GetControllerSessionBehavior(RequestContext requestContext, string controllerName)
    {
        return SessionStateBehavior.Default;
    }

    public void ReleaseController(IController controller)
    {
        var disposable = controller as IDisposable;
        if (disposable != null)
        {
            disposable.Dispose();
        }
    }
}
protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();

    WebApiConfig.Register(GlobalConfiguration.Configuration);
    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    RouteConfig.RegisterRoutes(RouteTable.Routes);
    BundleConfig.RegisterBundles(BundleTable.Bundles);
    AuthConfig.RegisterAuth();

    var factory = new CustomControllerFactory();
    ControllerBuilder.Current.SetControllerFactory(factory);
}

Unit Tests

    [TestClass]
    public class ProteinTrackerControllerTest
    {
        [TestMethod]
        public void WhenNothingHasHappenedTotalAndGoalAreZero()
        {
            ProteinTrackerController controller = new ProteinTrackerController(new StubTrackingService());

            var result = controller.Index() as ViewResult;

            Assert.AreEqual(0, result.ViewBag.Total);
            Assert.AreEqual(0, result.ViewBag.Goal);
        }

        [TestMethod]
        public void WhenTotalIsNonZero_AndAmountAdded_TotalIsIncreased()
        {
            var service = new StubTrackingService();
            service.Total = 10;

            ProteinTrackerController controller = new ProteinTrackerController(service);

            var result = controller.AddProtein(15) as ViewResult;

            Assert.AreEqual(25, result.ViewBag.Total);
            Assert.AreEqual(0, result.ViewBag.Goal);
        }
    }

    public class StubTrackingService : IProteinTrackingService
    {
        public int Total { get; set; }
        public int Goal { get; set; }
        public void AddProtein(int amount)
        {
            Total += amount;
        }
    }

fake IProteinTrackingService.  But this does allow us to just test the code inside ProteinTrackingController.

No best way to test a controller

Another Dependency

    public class ProteinTrackingService : IProteinTrackingService
    {
        private readonly IProteinRepository repository;

        public ProteinTrackingService(IProteinRepository repository)
        {
            this.repository = repository;
        }

Service’s dependency now abstracted away in an interface

    public class CustomControllerFactory : IControllerFactory
    {
        public IController CreateController(RequestContext requestContext, string controllerName)
        {
            if (controllerName.ToLower().StartsWith("proteintracker"))
            {
                var repository = new ProteinRepository();
                var service = new ProteinTrackingService(repository);
                var controller = new ProteinTrackerController(service);
                return controller;
            }

            var defaultFactory = new DefaultControllerFactory();
            return defaultFactory.CreateController(requestContext, controllerName);
        }

Getting complex to build ProteinTrackerController  Manual style of DI can only take us so far.. IoC can automate this for us.

photo

| | # 
( IoC )

Pluralsight video part1

image
Enable NuGet package restore

  • Project doesn’t have to be so large when zip up
  • Will be able to download and restore packages

Did an update all in NuGet – but this put on MVC5 and EF6!

image
Controller and a Service.

image
Doesn’t persist – creates a new version of the service each time.

    public class ProteinTrackingService
    {
        public int Total { get; set; }
        public int Goal { get; set; }

        public void AddProtein(int amount)
        {
            Total += amount;
        }
    }

public class ProteinTrackerController : Controller
{
    ProteinTrackingService proteinTrackingService = new ProteinTrackingService();
        
    public ActionResult Index()
    {
        ViewBag.Total = proteinTrackingService.Total;
        ViewBag.Goal = proteinTrackingService.Goal;

        return View();
    }

    public ActionResult AddProtein(int amount)
    {
        proteinTrackingService.AddProtein(amount);

        ViewBag.Total = proteinTrackingService.Total;
        ViewBag.Goal = proteinTrackingService.Goal;

        return View("Index");
    }
}
[TestMethod]
public void WhenNothingHasHappenedTotalAndGoalAreZero()
{
    ProteinTrackerController controller = new ProteinTrackerController();

    var result = controller.Index() as ViewResult;

    Assert.AreEqual(0, result.ViewBag.Total);
    Assert.AreEqual(0, result.ViewBag.Goal);
}

We’re actually testing the ProteinTrackingService here too.

| | # 
# Monday, 20 January 2014
( IoC | Unity | Windsor )

http://simpleprogrammer.com/

Maybe this will be a simple way forward for the Winter Project?  He is principally using Unity.

http://pluralsight.com/training/Courses/Description/ioc-aspdotnet-mvc4

image

 

image

we can make our own controller Factory

image

Also likely that we’ll want to inject into our views.  ViewResult comes back from an Action.

Basics

image
Want to invert the normal control classes have on their dependencies

ie nomally if we new up a class within another class, then this ‘dependency’ is problematic

  • Higher level classes are affected by lower level

eg if create instance of Laptop, we’d need to create instances of Battery, WallOutlet and SolarCell.

 

  • Our laptop is dependant on the IPowerSource interface
  • But how to create an instance of laptop and have battery, walloutlet etc..

Most Popular

  • Ninject 1
  • Unity 2 (MS implementation)

image

We can do this manually with Constructor based DI, but tedious and if some of power sources had their own dependencies, then complex and error prone.

Container

  • Tell which Interfaces are mapped to which implementations
  • Resolve them for us
  • eg IpowerSource should be mapped to battery class
  • When ask IoC container for instance of our laptop class
  • it will automatically construct laptop class with battery dependency passed in.

Therefore we need to hook into the correct part of MVC pipeline.

 


Windsor in here.

image

image

running as admin didn’t work

Found that if I saved the app on an AltF4, then reloaded (with DA off) it worked.

Controller Factory vs Dependency Resolver

Going to use DR as using Filter injection

| | # 
# Friday, 18 May 2012
( IoC | JonSkeet | TekPub )

In addition to handling instance construction, Inversion of Control containers can also handle lifetime and scope for you.

image

//.InSingletonScope resolve it later on, but resolve it only once, use the same instance after that.
//injector.Bind<IClock, SystemClock>().InSingletonScope();

.InSingletonScope resolve it later on, but resolve it only once, use the same instance after that.

Testability!

singletons – global state is the enemy of simplicity! let IoC containers do stuff.

logging is okay as its fine generally to have all the system call into the same logger

for the clock – Jon is always using an interface, and DI.

| | #