Dot-Net
SCT 過期時續訂 WCF 客戶端?
我正在使用 WCF 到使用安全模式“TransportWithMessageCredential”的肥皂端點。
WCF 客戶端/伺服器使用 SCT(安全上下文令牌)來維護安全連接,並且它在一般情況下按預期工作。
但是,在一段時間不活動之後,SCT 將過期,並且下一次方法呼叫將導致 MessageSecurityException:
從另一方收到不安全或不正確安全的故障。故障程式碼和細節見內部FaultException
內部異常:
無法處理該消息。這很可能是因為操作“ http://tempuri.org/IMyService/MyMethod ”不正確,或者因為消息包含無效或過期的安全上下文令牌,或者因為綁定之間不匹配。如果服務由於不活動而中止通道,則安全上下文令牌將無效。為了防止服務過早中止空閒會話,請增加服務端點綁定的接收超時。
在隨後的呼叫中,當我看到 CommunicationState 出現故障時,我會更新連接。但是我找不到在進行方法呼叫之前先發製人地檢查 SCT 是否已過期的方法。
您可以使用委託來解決您的問題。這將允許安全地呼叫該操作,如果失敗,則擷取異常,構造一個新的服務實例並再次執行該操作。
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); } } }
Service.Invoke(s => s.Method());然後,您可以像呼叫 IService.Method()一樣呼叫您的幫助程序類。
在第一個答案的基礎上,我提出了這個解決方案,它通常包裝由 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); } }要使用它,您需要做的就是:
ProxyWrapper<ServiceClient> client = new ProxyWrapper<ServiceClient>(); client.Invoke(s => s.SomeAction()); int val = client.Invoke<int>(s => s.ReturnsAnInteger());**注意:**由於我只使用客戶端代理的預設建構子,這就是所有這些支持。