Get the service contract instead of implementation from IResourceFactory.

Topics: Web Api
Jul 14, 2011 at 6:52 PM

I am currently using Unity as my IoC container.  With it, I am taking advantage of its interception features to handle some AOP-related concerns.  I have unity resolving my services by customizing the HttpHostConfiguration with the following:

.SetResourceFactory((serviceType, instanceContext, requestMessage) => 
                    _Container.Resolve(serviceType, new DependencyOverride<HttpRequestMessage>(requestMessage)), null)

In order for interception to work with the above code, all services must inherit from MarshalByRefObject. 

public abstract class ApiResourceBase : MarshalByRefObject ...

This allows me to create custom call handlers to intercept requests like below:

[ServiceContract]
public interface IExampleResource
{
    [WebGet(UriTemplate = "communities/{communityName}")]
    [RequiredCredentialsAuthorization(NetworkAuthorization.ClientAndUserCredentials)]  <<<<<
    ServiceResponse<Community> GetCommunityByName(String communityName);
}

With the above custom HandlerAttribute, ICallHandler, and IAuthorizationProvider, I can automate any kind of cross-cutting concern when a request comes in.  Attributes aren't required for this.  In this case, any request to "GetCommunityByName" service operation gets intercepted and the CurrentPrincipal is authorized.  This works perfectly so far, however, I am aware that interception via the TransparentProxyInterceptor is much slower than using an InterfaceInterceptor. Unity 2.0 Interception

 

Question: From the .SetResourceFactory() method, is there anyway I can get the service contract type instead of the concrete type?

This would allow desired interception behavior such as:

Container.RegisterType(typeof(IExampleResource), typeof(ExampleResource), new Interceptor<InterfaceInterceptor>(), new InterceptionBehavior<PolicyInjectionBehavior>());
&
_Container.Resolve(serviceContractType, new DependencyOverride<HttpRequestMessage>(requestMessage)), null)
&
No more need for all my resources / ApiResourceBase to inherit from MarshalByRefObject.

Hopefully I've stated this all legibly.  If any part is confusing I'd be happy to elaborate my goal.

Thanks in advance.

-Danny

Jul 14, 2011 at 7:06 PM

1) Try the following override SetResourceFactory(Func<Type, InstanceContext, HttpRequestMessage, object> getInstance, Action<InstanceContext, object> releaseInstance)

a) On the Func, use InstanceContext->Host->Endpoints->Contracts

2) WCF Web API provides alternative ways of doing AOP-like interception, namely via operation and message handlers.

3) For an example of using operation handlers to enforce authorization, check: https://github.com/pmhsfelix/Waaz

 

Jul 14, 2011 at 7:21 PM
Edited Jul 14, 2011 at 7:23 PM

Much thanks again for all your help.  Just refreshed the page to post that doing the following works:

.SetResourceFactory(
    (serviceType, instanceContext, requestMessage) =>
        {
            var serviceEndpoint = instanceContext.Host.Description.Endpoints.FirstOrDefault();
            if (serviceEndpoint == null)
            {
                return null;
            }
 
            return _Container.Resolve(serviceEndpoint.Contract.ContractType, new DependencyOverride<HttpRequestMessage>(requestMessage));
        },
    null)