VS2022 C# Standard下SOAP WebService的XML命名空间pgim修改方法
修改SOAP请求XML命名空间(添加pgim命名空间)
针对VS2022中用C# Standard开发SOAP WebService时的命名空间修改需求,以下是几种实用方案:
方案1:通过契约属性直接指定命名空间
如果基于WCF开发,最直接的方式是在服务契约和数据契约上配置Namespace属性,生成的SOAP消息会自动套用指定的命名空间:
// 服务契约指定pgim命名空间 [ServiceContract(Namespace = "http://your-domain.com/pgim")] public interface IPgimService { [OperationContract] PgimResponse HandlePgimRequest(PgimRequest request); } // 数据契约同步指定命名空间 [DataContract(Namespace = "http://your-domain.com/pgim")] public class PgimRequest { [DataMember] public string RequestContent { get; set; } } [DataContract(Namespace = "http://your-domain.com/pgim")] public class PgimResponse { [DataMember] public string ResponseContent { get; set; } }
部署服务后,SOAP请求/响应的XML节点会自动带上http://your-domain.com/pgim命名空间,可根据需求调整域名部分。
方案2:自定义消息格式化器(复杂场景适配)
如果需要更灵活的XML修改(比如替换已有命名空间、自定义前缀),可以实现WCF的消息格式化接口,手动干预SOAP消息的XML结构:
服务端自定义格式化器示例
public class PgimNamespaceFormatter : IDispatchMessageFormatter { private readonly IDispatchMessageFormatter _originalFormatter; private const string TargetNamespace = "http://your-domain.com/pgim"; private const string Prefix = "pgim"; public PgimNamespaceFormatter(IDispatchMessageFormatter originalFormatter) { _originalFormatter = originalFormatter; } public void DeserializeRequest(Message message, object[] parameters) { // 解析并修改SOAP请求XML var xmlDoc = new XmlDocument(); using (var reader = message.GetReaderAtBodyContents()) { xmlDoc.Load(reader); // 为根节点添加pgim命名空间前缀 xmlDoc.DocumentElement.SetAttribute($"xmlns:{Prefix}", TargetNamespace); // 递归修改所有子节点的前缀 SetNodePrefix(xmlDoc.DocumentElement, Prefix); // 重新构造请求消息 var modifiedMessage = Message.CreateMessage(message.Version, message.Headers.Action, new XmlNodeReader(xmlDoc)); _originalFormatter.DeserializeRequest(modifiedMessage, parameters); } } public Message SerializeReply(MessageVersion messageVersion, object[] parameters, object result) { var replyMessage = _originalFormatter.SerializeReply(messageVersion, parameters, result); // 同理可修改响应消息的命名空间,逻辑与请求处理一致 return replyMessage; } private void SetNodePrefix(XmlNode node, string prefix) { if (node is XmlElement element) { element.Prefix = prefix; foreach (XmlNode child in node.ChildNodes) { SetNodePrefix(child, prefix); } } } }
注册格式化器到服务端点
需要创建自定义行为类,将格式化器注入服务端点:
public class PgimServiceBehavior : WebHttpBehavior { protected override IDispatchMessageFormatter GetRequestDispatchFormatter(OperationDescription operationDescription, ServiceEndpoint endpoint) { var originalFormatter = base.GetRequestDispatchFormatter(operationDescription, endpoint); return new PgimNamespaceFormatter(originalFormatter); } } // 服务启动时注册行为 var serviceHost = new ServiceHost(typeof(PgimService)); foreach (var endpoint in serviceHost.Description.Endpoints) { endpoint.Behaviors.Remove<WebHttpBehavior>(); endpoint.Behaviors.Add(new PgimServiceBehavior()); } serviceHost.Open();
方案3:修改客户端代理类(如果是客户端发送请求)
如果是通过VS“添加服务引用”生成的客户端代理,可通过两种方式调整命名空间:
- 添加引用时指定:在“添加服务引用”窗口点击“高级”,在“命名空间”输入框填写pgim对应的命名空间;
- 命令行生成代理:用
svcutil.exe生成时直接指定命名空间:
svcutil.exe http://your-service-url?wsdl /namespace:*,http://your-domain.com/pgim /out:PgimServiceProxy.cs
此命令会将所有代理类的命名空间统一替换为目标pgim命名空间。
方案4:配置文件中添加端点行为(快速修改前缀)
若仅需为XML节点添加pgim前缀,可通过配置文件结合消息检查器实现:
配置文件(app.config/web.config)
<system.serviceModel> <behaviors> <endpointBehaviors> <behavior name="PgimNamespaceBehavior"> <messageInspector> <add type="YourAssembly.PgimNamespaceInspector, YourAssembly" /> </messageInspector> </behavior> </endpointBehaviors> </behaviors> <services> <service name="YourNamespace.PgimService"> <endpoint address="" binding="basicHttpBinding" contract="YourNamespace.IPgimService" behaviorConfiguration="PgimNamespaceBehavior" /> </service> </services> </system.serviceModel>
实现消息检查器
public class PgimNamespaceInspector : IDispatchMessageInspector { private const string TargetNamespace = "http://your-domain.com/pgim"; private const string Prefix = "pgim"; public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext) { var xmlDoc = new XmlDocument(); using (var reader = request.GetReaderAtBodyContents()) { xmlDoc.Load(reader); xmlDoc.DocumentElement.SetAttribute($"xmlns:{Prefix}", TargetNamespace); foreach (XmlElement element in xmlDoc.DocumentElement.GetElementsByTagName("*")) { element.Prefix = Prefix; } var modifiedRequest = Message.CreateMessage(request.Version, request.Headers.Action, new XmlNodeReader(xmlDoc)); request = modifiedRequest; return null; } } public void BeforeSendReply(ref Message reply, object correlationState) { // 如需修改响应消息,重复上述XML处理逻辑即可 } }
内容的提问来源于stack exchange,提问作者Roberto Villavicencio
相关产品推荐
相关产品推荐

