Unity Interception: Mixing Enterprise Library call with my own ICallHandler (fixed)

Sep 9, 2011 at 5:02 PM
Edited Sep 9, 2011 at 8:01 PM

Hi,

I am developing a classic three-tier MVC3 web application and I want to add logging, authentication and validation logic to the calls to my business layer. I am trying out various options and the one that I think I will go with is Enterprise Library Validation on method calls (I can't reproduce its features easily) and my own ICallHandler for logging and authentication (I know EntLib has that but it seemed more heavyweight than I wanted).

I have developed a small series of Unit Tests just to check that things are happening as I expect and they don't. Basically in a case where the validation passes my ICallHandler is called three times. In the case where the validation fails my ICallHanlder is called only once (and obviously before the validation calls an exception).

Here is the code that sets up the resolver:

        public static UnityContainer SetupResolverEnterpriseLibraryAndOwnHandler(ICallHandler myMethodHandler)
        {

            var container = new UnityContainer();

            // register all your components with the container here
            // e.g. container.RegisterType<ITestService, TestService>();            

            ////Add link to Enterprise Library
            container.AddNewExtension<EnterpriseLibraryCoreExtension>();

            ////Now enable Interception
            container.AddNewExtension<Interception>();

            container.AddNewExtension<Interception>();
            container.Configure<Interception>()
                     .AddPolicy("TestMethodValidation")
                        .AddMatchingRule<AssemblyMatchingRule>(new InjectionConstructor("TR56UnityInterception"))
                        .AddCallHandler(myMethodHandler)
                        .AddCallHandler(typeof(ValidationCallHandler), new InjectionConstructor("", SpecificationSource.Attributes));

            //Now register the types that need interception
            container.RegisterType<ITestClass1, TestClass1>(new InjectionConstructor(1, "main"),
                                                             new Interceptor<VirtualMethodInterceptor>(),
                                                             new InterceptionBehavior<PolicyInjectionBehavior>());

            return container;

        }

And here is my unit test that fails on the last assert saying 'Expected: 1 but was 3"

        [Test]
        public void Test15TryCountMethodAndRangeValidatorToPass()
        {

            //SETUP
            var countCallHandler = new CountCallHandler(1);
            var container = SetupUnity.SetupResolverEnterpriseLibraryAndOwnHandler(countCallHandler);

            //ATTEMPT
            var testClass1 = container.Resolve<ITestClass1>();

            //VERIFY
            countCallHandler.NumTimesCalled.ShouldEqual(0);
            testClass1.MyMethod(1).ShouldEqual("positive");
            countCallHandler.NumTimesCalled.ShouldEqual(1);
        }

I wonder if you have any idea why this is happening.

One other points while I am at it: I am trying to control the order that the various interceptions are called in, but I'm not sure how to do that? What Order number does EntLib's ValidationCallHandler have?

Thanks in advance

Jon Smith
Selective Analytics

 

Sep 9, 2011 at 5:10 PM

Hi,

In putting up this post I noticed that the line

container.AddNewExtension<Interception>();

was in twice (bad cut and paste). I took out the double AddNewExtension<Interception> and the test now fails with 'Expected: 1 but was 2' (not three in the former case). Obviously still not right, but at least one bug is found

Jon Smith
Selective Analytics

 

Sep 9, 2011 at 5:57 PM
Edited Sep 9, 2011 at 8:01 PM

Removed this post as saw an error in it

Jon Smith
Selective Analytics

 

Sep 9, 2011 at 6:42 PM
Edited Sep 9, 2011 at 8:00 PM

OK. Found the answer to the main problem, with the help of the last bug. It seems that

container.AddNewExtension<EnterpriseLibraryCoreExtension>();

has the effect of adding the Interception extention to Unity. Why adding the Interception extention mutiple times is a problem I really don't know, but it is definately the bug I was suffering with. For completeness here is my new setup of the Unity resolver.

        public static UnityContainer SetupResolverEnterpriseLibraryAndOwnHandler(ICallHandler myMethodHandler)
        {

            var container = new UnityContainer();

            // register all your components with the container here
            // e.g. container.RegisterType<ITestService, TestService>();            

            //Add link to Enterprise Library
            container.AddNewExtension<EnterpriseLibraryCoreExtension>();

            //Add link to Enterprise Library (which also enables Interception)
            container.AddNewExtension<EnterpriseLibraryCoreExtension>();

            container.Configure<Interception>()
                     .AddPolicy("TestMethodValidation")
                        .AddMatchingRule<AssemblyMatchingRule>(new InjectionConstructor("TR56UnityInterception"))
                        .AddCallHandler(myMethodHandler)
                        .AddCallHandler(typeof(ValidationCallHandler), new InjectionConstructor("", SpecificationSource.Attributes));

            //Now register the types that need interception
            container.RegisterType<ITestClass1, TestClass1>(new InjectionConstructor(1, "main"),
                                                             new Interceptor<VirtualMethodInterceptor>(),
                                                             new InterceptionBehavior<PolicyInjectionBehavior>("MySetup"));


            foreach (var containerRegistration in container.Registrations)
            {
                Debug.WriteLine(string.Format("Registered Type {0}, linked to {1}, under name {2}",
                    containerRegistration.RegisteredType, containerRegistration.MappedToType, containerRegistration.Name));
            }

            return container;

        }

I still have the question of how to control the order of ICallHandler and the EntLib ValidationCallHandler, but I will ask that on the EntLib forum.

Hopefully this post will be useful to someone else (maybe the Unity team might like to look at why adding the intercpetion extention twice is a problem).

Happy coding

Jon Smith
Selective Analytics

Sep 9, 2011 at 7:57 PM
Edited Sep 9, 2011 at 8:03 PM

OK, finally found all the answers. ValidationCallHandler has a construtor with an Order element in it, so that is fixed my last problem.

I should say that the behaviour (bug?) where the ICallHandler is called twice ifs known about, but in a different form. See this discussion in the Enterprise Library Forum for more details.

Hope this helps someone else.

Jon Smith
Selective Analytics