Automatically repeat WCF client request based on interception and return value

Is it possible to intercept the result of a WCF call and repeat the operation?

For example, the return value of an operation may contain a status code that indicates that the session token I passed to the original call has expired. In this case, I can get a new session token and retry the call with a new session token.

Is it possible to perform this retry operation using WCF interception of the return value, checking it, and then repeating the call completely transparent to the calling statement?

I already know how to check calls using IParameterInspector , but at this point there is no built-in way to call back.

I am looking for a method that uses pure interception, so that it is completely transparent to the client.

+4
source share
3 answers

Assuming you want this to happen on the client side, you can use IClientMessageInspector - if you want to implement this on the server side you can create an IDispatchMessageInspector .

By IClientMessageInspector , you check the result in the AfterReceiveReply event, and if you need to try again, you can initiate a retry ... when the call returns, you simply “overwrite” the result, which made you retry with a new one ... thus the calling call the operation does not notice anything (except that the call sometimes takes a little longer).

Although you should be careful in implementing the retry function (a possible problem with re-registration should be handled appriopriately).

For some sample code (without the attempt itself) see http://weblogs.asp.net/paolopia/archive/2007/08/23/writing-a-wcf-message-inspector.aspx

EDIT - according to the comments:

How to implement a repeat operation depends on several aspects.

Basically, you need to associate the call of the request message and the request messages with a playback message.

One way to do this is to implement IClientMessageFormatter.SerializeRequest OR IParameterInspector - this will allow you to record which method was called and which message object was created for it.

By IClientMessageInspector.BeforeSendRequest , you can assign a unique correlationState , which in turn allows you to associate the response message in your implementation with IClientMessageInspector.AfterReceiveReply , since the Framework will call your implementation with it as a second parameter.

From there, you can use Reflection to call back (all the necessary information is available, since you wrote down the type and method and parameters in your implementation of IClientMessageFormatter and / or IParameterInspector ) and overwrite the response message with a new answer.

Another (and possibly much simpler) option would be to implement a custom WCF client class and provide this to the caller ... this allows you to stay out of the mess of different inspectors, etc. and gives great control over any triggered operation.

EDIT 2 - according to comments:

When implementing IClientMessageInspector you will also need to implement IEndpointBehavior , which in turn has an ApplyClientBehavior method, which is called by WCF to add your IClientMessageInspector . In this method, you create an instance of your implementation that takes one argument in the constructor, which in turn is endpoint.Contract.ContractType or clientRuntime.ContractClientType . you store this type in the inspector ... for tips on how to do this, for example, http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/19500d14-78b7-4356-b817-fcc9abc2afcf/

+3
source

You can use the AOP structure for this. Unity has enough functionality for this, or you might consider using the “right” AOP infrastructure such as LinFu or PostSharp.

+1
source

I would use the unity interface / virtual interception method.

 _unityContainer.AddNewExtension<Interception>(); _unityContainer.RegisterType<ITestCaching, TestCaching>( new Interceptor<InterfaceInterceptor>(), new InterceptionBehavior<PolicyInjectionBehavior>()); _unityContainer.RegisterType<XRepository>( new Interceptor<VirtualMethodInterceptor>(), new InterceptionBehavior<PolicyInjectionBehavior>()); 

I use the policy injection behavior so that I can use attributes to add additional behavior. custom attributes involved in the interception will need to inherit HandlerAttribute and implement:

 public override ICallHandler CreateHandler(IUnityContainer container) { return new RetryCallHandler(container, ConfigurationName); } 

The behavior will be implemented in a class that implements ICallHandler

 public class RetryCallHandler : ICallHandler, IDisposable { public IMethodReturn Invoke(IMethodInvocation args, GetNextInterceptionBehaviorDelegate getNext) { Exception exception = null; int retryCounter = MAX_RETRIES; do { exception = null; try { var intercepted = getNext(); IMethodReturn methodReturn = intercepted(args, getNext); return methodReturn; } catch (Exception ex) { exception = ex; } }while(exception!=null && retryCounter-- > 0); return args.CreateExceptionMethodReturn(exception); } } 

I have not compiled or tested the above code.

The only problems I foresee is GetNextInterceptionBehaviorDelegate if you have multiple hooks. You can control the order of call handlers, so just make sure it's the last in the chain.

0
source

Source: https://habr.com/ru/post/1379802/


All Articles