SOAP WCF WS-Addressing自定义Action头报重复头异常如何解决?
问题原因
WCF客户端生成的代理类在调用时会默认自动生成一个Action头,命名空间为http://schemas.microsoft.com/ws/2005/05/addressing/none,你通过OutgoingMessageHeaders.Action赋值的操作会额外新增一个同命名空间的Action头,最终导致重复冲突。
解决方案1:直接修改现有头(适配单接口修改场景)
在赋值前先删除已存在的同命名空间Action头,再进行赋值即可,代码修改如下:
public async Task<getAttorneyResponseStructure> GetAttorneyAsync(GetAttorneyRequestStructure getAttorneyRequestStructure) { try { using (new OperationContextScope(Client.InnerChannel)) { getAttorneyRequestStructure.AttorneyHeader = Header; // To头无默认冲突可直接赋值 OperationContext.Current.OutgoingMessageHeaders.To = new Uri("http://rydwvgsn01.spga.gov.sa/GSBExpress/Legal/MOJAttorneyInquiry/2.0/AttorneyInquiryService.svc"); // 先移除已存在的默认Action头 var defaultActionNamespace = "http://schemas.microsoft.com/ws/2005/05/addressing/none"; OperationContext.Current.OutgoingMessageHeaders.RemoveAll("Action", defaultActionNamespace); // 赋值自定义Action OperationContext.Current.OutgoingMessageHeaders.Action = "http://tempuri.org/IAttorneyInquiryService/GetAttorney"; // 如需自定义Action头的命名空间,替换上一行的赋值逻辑即可 // var customActionHeader = MessageHeader.CreateHeader("Action", "你的自定义命名空间", "http://tempuri.org/IAttorneyInquiryService/GetAttorney"); // OperationContext.Current.OutgoingMessageHeaders.Add(customActionHeader); return await Client.GetAttorneyAsync(getAttorneyRequestStructure); } } catch (Exception e) { throw; } }
解决方案2:使用IClientMessageInspector全局拦截修改(适配多接口统一修改场景)
如果项目内多个接口都需要自定义SOAP头,可通过消息拦截器统一处理,避免每个接口重复写逻辑:
- 实现
IClientMessageInspector接口处理消息修改逻辑
public class CustomSoapHeaderInspector : IClientMessageInspector { public void AfterReceiveReply(ref Message reply, object correlationState) { // 响应处理逻辑按需添加即可 } public object BeforeSendRequest(ref Message request, IClientChannel channel) { // 修改To头 request.Headers.To = new Uri("http://rydwvgsn01.spga.gov.sa/GSBExpress/Legal/MOJAttorneyInquiry/2.0/AttorneyInquiryService.svc"); // 移除默认Action头 var defaultActionNs = "http://schemas.microsoft.com/ws/2005/05/addressing/none"; request.Headers.RemoveAll("Action", defaultActionNs); // 设置自定义Action,按需调整命名空间 request.Headers.Action = "http://tempuri.org/IAttorneyInquiryService/GetAttorney"; return null; } }
- 实现
IEndpointBehavior将拦截器注入客户端终结点
public class CustomSoapHeaderBehavior : IEndpointBehavior { public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) { } public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime) { clientRuntime.ClientMessageInspectors.Add(new CustomSoapHeaderInspector()); } public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher) { } public void Validate(ServiceEndpoint endpoint) { } }
- 客户端初始化时添加该行为即可全局生效
Client.Endpoint.EndpointBehaviors.Add(new CustomSoapHeaderBehavior());
内容的提问来源于stack exchange,提问作者Nasser X
相关产品推荐
相关产品推荐

