Using Unity Interception w/WCF

Mar 3, 2009 at 8:54 PM
I've been trying to get Unity Interception to work with WCF but I can't seem to get the interceptor to fire correctly.

I host my service within a factory like:

public

 

class DocumentTemplateServiceHostFactory : ServiceHostFactory
{
    protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
    {
        UnityServiceHost host = new UnityServiceHost(serviceType, baseAddresses);
        UnityContainer unity = new UnityContainer();

 

 

        unity.AddNewExtension<

Interception>(); 
        unity.RegisterType<
IDocumentTemplateService, DocumentTemplateService>().Configure<Interception>().SetInterceptorFor<IDocumentTemplateService>(new InterfaceInterceptor());

 

        host.Container = unity;

 

        return host;
      }
}

I setup an attribute to fire

 

namespace

 

M.PC.Service

 

{

 

public class PCSecurityAttribute : HandlerAttribute

 

 

 

 

{

 

public PCSecurityAttribute(Modules module, int modulePermission)

 

{

SecurityModule = module;

SecurityModulePermission = modulePermission;

}

 

public Modules SecurityModule

 

{

 

get;

 

 

set;

 

}

 

public int SecurityModulePermission

 

{

 

get;

 

 

set;

 

}

 

public override ICallHandler CreateHandler(IUnityContainer container)

 

{

 

return new PCSecurityCallHandler(SecurityModule, SecurityModulePermission);

 

}

}

}

 

namespace

 

M.PC.Service

 

{

 

public class PCSecurityCallHandler : ICallHandler

 

 

 

 

 

{

 

private Modules securityModule;

 

 

private int securityModulePermission;

 

 

public PCSecurityCallHandler(Modules module, int modulePermission)

 

{

securityModule = module;

securityModulePermission = modulePermission;

Order = 0;

}

 

 

public PCSecurityCallHandler(int order, Modules module, int modulePermission)

 

{

securityModule = module;

securityModulePermission = modulePermission;

Order = order;

}

 

public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)

 

{

 

bool validPermission = false;

 

 

// check security permission

 

 

 

 

 

 

IMethodReturn result;

 

 

if (validPermission)

 

result = getNext().Invoke(input, getNext);

 

else

 

 

 

// exception

 

 

//throw new SecurityAccessDeniedException("The current user does not have security permissions to call this module.");

 

 

return result;

 

}

 

public int Order

 

{

 

get;

 

 

set;

 

}

}

}

 

but none of the attribute code fires and my method is not intercepted...  what am i doing wrong???

Mar 3, 2009 at 11:57 PM
Edited Mar 4, 2009 at 12:00 AM
Tip: Blog on copy/paste source code from Visual Studio => HERE

Hi mupchu777,

I'm new to interception so please educate me if I got things backwards/wrong but I was able to make your code work with the following Unit Test.  I made numerous assumptions on the context of your code and made minor modifications (took out Modules because I didn't know what it was).   If I did figure things out correctly then the answer lies within the Unit Test usage below:

        public class MockHostFactory : DocumentTemplateServiceHostFactory

        {

            public void CreateHost()

            {

 

                Uri[] test =  {new Uri("c:\\")};

                UnityServiceHost host = (UnityServiceHost
                     CreateServiceHost(GetType(), test);

                IDocumentTemplateService service =
                     host.Container.Resolve<IDocumentTemplateService>();

 

                bool isFailed = false;

                try

                {

                    service.MyMethod();

                }

                catch (Exception ex)

                {

                    isFailed = true;

                }

                Assert.IsTrue(isFailed);

 

                service.NoSecurityMethod();

            }

        }

 

        [TestMethod]

        public void CanInterceptForSecurityCheck()

        {

 

            MockHostFactory factory = new MockHostFactory();

            factory.CreateHost();

 

        }


using System;

using System.ServiceModel;

using System.ServiceModel.Activation;

using System.ServiceModel.Security;

using Microsoft.Practices.Unity;

using Microsoft.Practices.Unity.InterceptionExtension;

using SDMSService.Provider.M.PC.Service;

 

namespace SDMSService.Provider

{

    public class Modules

    {

    }

 

    public interface IDocumentTemplateService

    {

        int MyMethod();

        int NoSecurityMethod();

    }

 

    public class DocumentTemplateService : IDocumentTemplateService

    {

        [PCSecurityAttribute(20)]

        public int MyMethod()

        {

            return -1;

        }

 

        [PCSecurityAttribute(0)]

        public int NoSecurityMethod()

        {

            return -1;

        }

    }

 

    public class UnityServiceHost : ServiceHost

    {

        public IUnityContainer Container { get; set; }

        public UnityServiceHost(Type serviceType, Uri[] baseAddresses)

        {

        }

    }

 

    public class DocumentTemplateServiceHostFactory : ServiceHostFactory

    {

        protected override ServiceHost CreateServiceHost(
             Type serviceType, Uri[] baseAddresses)

        {

            UnityServiceHost host = new UnityServiceHost(serviceType, baseAddresses);

            UnityContainer unity = new UnityContainer();

 

            unity.AddNewExtension<Interception>();

            unity.RegisterType<IDocumentTemplateService, DocumentTemplateService>()

                .Configure<Interception>()

                .SetInterceptorFor<IDocumentTemplateService>(
                  new InterfaceInterceptor());

 

            host.Container = unity;

            return host;

        }

    }

 

    namespace M.PC.Service

    {

        public class PCSecurityAttribute : HandlerAttribute

        {

            public PCSecurityAttribute(int modulePermission)

            {

                //SecurityModule = module;

                SecurityModulePermission = modulePermission;

            }

 

            public Modules SecurityModule { get; set; }

            public int SecurityModulePermission { get; set; }

 

            public override ICallHandler CreateHandler(IUnityContainer container)

            {

                return new PCSecurityCallHandler(
                   SecurityModule, SecurityModulePermission);

            }

        }

    }

 

 

    namespace M.PC.Service

    {

        public class PCSecurityCallHandler : ICallHandler

        {

            private Modules securityModule;

            private int securityModulePermission;

 

            public PCSecurityCallHandler(int modulePermissions)

            {

 

            }

            public PCSecurityCallHandler(Modules module, int modulePermission)

            {

                securityModule = module;

                securityModulePermission = modulePermission;

                Order = 0;

            }

 

            public PCSecurityCallHandler(
                int order, Modules module, int modulePermission)

            {

                securityModule = module;

                securityModulePermission = modulePermission;

                Order = order;

            }

 

            public IMethodReturn Invoke(
                IMethodInvocation input, GetNextHandlerDelegate getNext)

            {

                bool validPermission = false;

 

                // check security permission

                IMethodReturn result;

                if (validPermission || securityModulePermission==0)

                    result = getNext().Invoke(input, getNext);

                else

                    // exception

                    throw new SecurityAccessDeniedException("The current user does not have security permissions to call this module.");

                return result;

            }

 

            public int Order { get; set; }

        }

    }

}

Mar 4, 2009 at 1:21 AM
I think the issue is due to it being an IIS hosted WCF service (which it doesn't look like was factored in your app).  I set up the svc file to point to the factory which uses unity to setup the container for the service.  I'm not sure that is represented here,  it looks like unity is invoked directly rather than through the iis infrastructure (which is where the problem seems to be coming from).  At this point I just want to be able to use interception in my WCF services to inject a security check.  When other develoers are creating services I'd like to allow them to declaratively define a security check that can be processed at run time.
Mar 4, 2009 at 1:04 PM
Perhaps your solution will lie in the following blog then?

http://www.global-webnet.net/blogengine/post/2009/01/03/Integrating-IIS-WCF-and-Unity.aspx

I use WCF Behaviors so that Unity actually resolves the WCF Service interface.   Usage is pretty simply, simply add a reference to my UnityContrib project (no relations to UnityContributions) and configure your Web.Config and Walla!  WCF is using a Unity section in the Web.Config to bootstrap your WCF service; everything after that is elementary.
Apr 27, 2009 at 11:49 PM
I also could not get InterfaceInterceptor to work with WCF. See http://unity.codeplex.com/WorkItem/View.aspx?WorkItemId=3388