Renewing a WCF client when SCT has expired?

后端 未结 4 1557
一生所求
一生所求 2020-12-23 23:34

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

相关标签:
4条回答
  • 2020-12-24 00:04

    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.

    0 讨论(0)
  • 2020-12-24 00:11

    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();
        }
      }
    }
    
    0 讨论(0)
  • 2020-12-24 00:16

    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

    0 讨论(0)
  • 2020-12-24 00:18

    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().

    0 讨论(0)
提交回复
热议问题