I am using WCF to a soap endpoint using security mode \"TransportWithMessageCredential\".
The WCF client/server uses SCT (Security Context Token) to maintain a secur
Building on the first answer, I came up with this solution that generically wraps the auto-generated client proxies created by svcutil.exe:
public class ProxyWrapper<T> where T : ICommunicationObject
{
private T _service;
public ProxyWrapper()
{
_service = CreateNewInstance();
}
public void Invoke(Action<T> action)
{
try
{
action(_service);
}
catch (MessageSecurityException)
{
if (_service.State != CommunicationState.Faulted)
{
throw;
}
_service.Abort();
_service = CreateNewInstance();
action(_service);
}
}
public TResult Invoke<TResult>(Func<T, TResult> func)
{
try
{
return func(_service);
}
catch (MessageSecurityException)
{
if (_service.State != CommunicationState.Faulted)
{
throw;
}
_service.Abort();
_service = CreateNewInstance();
return func(_service);
}
}
private T CreateNewInstance()
{
Type type = typeof(T);
return (T)type.GetConstructor(Type.EmptyTypes).Invoke(null);
}
}
To use this, all you need to do is:
ProxyWrapper<ServiceClient> client = new ProxyWrapper<ServiceClient>();
client.Invoke(s => s.SomeAction());
int val = client.Invoke<int>(s => s.ReturnsAnInteger());
Note: Since I'm only using the default constructor for the client proxies, that's all this supports.
You might be able to use the decorater pattern to handle exceptions with WCF proxies. If this path is open to you, you can consider something like this set-up which will handle the proxy faulting and re-initialise it for callers. Subsequent exceptions will be thrown up to the caller.
//Proxy implements this
interface IMyService
{
void MyMethod();
}
//Decorator 1
public class MyServiceProxyRetryingDecorator : IMyService
{
//This is the real proxy that might be faulted
private realProxy = new RealProxy();
public void MyMethod()
{
ReEstablishProxyIfNecessary();
//now just pass the call to the proxy, if it errors again,
//do more handling or let the exception bubble up
realProxy.MyMethod();
}
private void ReEstablishProxyIfNecessary()
{
if(realProxy.CommunicationState == CommunicationState.Faulted)
{
realProxy.Abort();
realProxy = new RealProxy();
}
}
}
An different version of the decorator could have the decorator handling your MessageSecurityException, and re-initialising the real proxy when it is caught:
//Decorator 2
public class MyServiceProxyExceptionHandlingDecorator : IMyService
{
//This is the real proxy that might be faulted
private realProxy = new RealProxy();
public void MyMethod()
{
try {realProxy.MyMethod(); }
catch (ExceptionYouAreInterestedIn ex)
{
ReEstablishProxyIfNecessary();
realProxy.MyMethod(); //do it again
}
}
private void ReEstablishProxyIfNecessary()
{
if(realProxy.CommunicationState == CommunicationState.Faulted)
{
realProxy.Abort();
realProxy = new RealProxy();
}
}
}
Take a look at this post where you can download a proxy wrapper that does a retry when the session expires.
http://www.dasblonde.net/2008/04/24/MyProxyWrapperAndTheEVILSUOFile.aspx
You could resolve your issues by using delegates. This will allow to safely invoke the action and, if fails, catch the exception, construct a new service instance and perform the action again.
using System;
using System.ServiceModel;
using System.ServiceModel.Security;
public static class Service
{
private static IService _service;
public static void Invoke(Action<IService> action)
{
try
{
action(_service);
}
catch (MessageSecurityException)
{
if (_service.State != CommunicationState.Faulted)
{
throw;
}
_service.Abort();
_service = CreateFreshInstance();
action(_service);
}
}
}
You could then call your helper class like Service.Invoke(s => s.Method());
to invoke the IService.Method().