C# .NET调用SOAP API缺命名空间前缀 如何为现有类加前缀解决报错
解决方案
问题根源
自动生成的服务代码中,XmlElementAttribute的Form属性被设置为XmlSchemaForm.Unqualified,同时序列化时没有绑定目标命名空间和ws前缀的映射关系,导致请求的方法节点未携带命名空间前缀,服务端无法识别。
方案1:修改partial类属性(推荐,不会被服务引用更新覆盖)
不要直接修改自动生成的Resources.cs文件,新建一个独立的.cs文件,定义同名partial类覆盖属性标注:
using System.Xml.Serialization; using System.ServiceModel; using System.Xml.Schema; // 命名空间必须和自动生成的类保持完全一致 namespace SystemRefresh.ConfigurationServices { [XmlRoot("getLocationsByCriteria", Namespace = "http://services.timecommerce.timetrade.com/ws")] public partial class getLocationsByCriteriaRequest { [XmlElement(Form = XmlSchemaForm.Qualified, Namespace = "http://services.timecommerce.timetrade.com/ws")] public locationSearchCriteria locationSearchCriteria; } }
调用请求时绑定命名空间前缀映射:
// 构造请求参数 var request = new getLocationsByCriteriaRequest { locationSearchCriteria = new locationSearchCriteria { locationExternalId = "sonoram3n", locationGroupId = 0 } }; // 绑定ws前缀和目标命名空间的映射 var serializerNamespaces = new XmlSerializerNamespaces(); serializerNamespaces.Add("ws", "http://services.timecommerce.timetrade.com/ws");
方案2:自定义消息检查器(万能兼容方案)
如果方案1不生效,可以通过自定义客户端消息检查器,在请求发出前直接修改XML内容:
实现消息检查器接口
using System.ServiceModel; using System.ServiceModel.Dispatcher; using System.Xml; using System.IO; public class SoapNamespacePrefixInspector : IClientMessageInspector { public void AfterReceiveReply(ref Message reply, object correlationState) { // 无需处理返回值,留空即可 } public object BeforeSendRequest(ref Message request, IClientChannel channel) { // 将消息转为XML文档 var xmlDoc = new XmlDocument(); using (var ms = new MemoryStream()) { using (var writer = XmlWriter.Create(ms)) { request.WriteMessage(writer); writer.Flush(); ms.Position = 0; xmlDoc.Load(ms); } } // 找到Body节点下的方法节点,添加ws前缀 var bodyNode = xmlDoc.GetElementsByTagName("Body", "http://schemas.xmlsoap.org/soap/envelope/")[0]; var methodNode = bodyNode.FirstChild; if (methodNode.LocalName == "getLocationsByCriteria" && methodNode.NamespaceURI == "http://services.timecommerce.timetrade.com/ws") { // 新增ws命名空间声明 var nsAttr = xmlDoc.CreateAttribute("xmlns:ws"); nsAttr.Value = "http://services.timecommerce.timetrade.com/ws"; methodNode.Attributes.Append(nsAttr); // 给方法节点添加ws前缀 methodNode.Prefix = "ws"; } // 重新构造请求消息 using (var ms = new MemoryStream()) { using (var writer = XmlWriter.Create(ms)) { xmlDoc.WriteTo(writer); writer.Flush(); ms.Position = 0; using (var reader = XmlReader.Create(ms)) { request = Message.CreateMessage(reader, int.MaxValue, request.Version); } } } return null; } }
注册检查器到SOAP客户端
// 替换为你实际生成的SOAP客户端类名 var soapClient = new YourSoapServiceClient(); soapClient.Endpoint.Behaviors.Add(new SoapNamespacePrefixInspector()); // 后续正常调用接口即可 var response = soapClient.getLocationsByCriteria(request);
内容的提问来源于stack exchange,提问作者Nick Kester
相关产品推荐
相关产品推荐

