You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

问询:.NET如何在WSDL生成的代理中移除请求空标签?

移除Web服务请求中的空标签:代理代码层的实现方案

嗨,这个需求我太熟悉了——改WSDL确实是合规的做法,但还要和外部伙伴同步验证,成本不低。其实在生成的代理代码里,完全可以通过拦截序列化后的请求内容来移除空标签,不用动WSDL,下面给你两种最常用的简便方案:

方案一:针对传统ASMX代理(SoapHttpClientProtocol)

如果你的代理类是用wsdl.exe生成的、继承自SoapHttpClientProtocol的传统ASMX代理,可以重写GetWebRequest方法,在请求发送前修改XML内容:

  1. 找到生成的代理类,添加以下重写方法:
protected override WebRequest GetWebRequest(Uri uri)
{
    WebRequest request = base.GetWebRequest(uri);
    if (request is HttpWebRequest httpRequest)
    {
        httpRequest.ContentLength = 0; // 先清空默认长度,后续重新计算
        using (MemoryStream ms = new MemoryStream())
        {
            // 序列化请求对象到内存流
            var requestType = this.GetType().GetMethod("YourRequestMethod").GetParameters()[0].ParameterType;
            XmlSerializer serializer = new XmlSerializer(requestType);
            serializer.Serialize(ms, yourRequestObject); // 替换为实际请求对象变量
            ms.Position = 0;

            // 加载XML并移除空标签(无内容且无子元素的节点)
            XDocument doc = XDocument.Load(ms);
            doc.Descendants().Where(e => string.IsNullOrWhiteSpace(e.Value) && !e.HasElements).Remove();

            // 将修改后的XML写入请求流
            using (Stream requestStream = httpRequest.GetRequestStream())
            {
                doc.Save(requestStream);
                httpRequest.ContentLength = requestStream.Length;
            }
        }
    }
    return request;
}

注意:要替换代码里的YourRequestMethod和yourRequestObject为你实际调用的请求方法与参数对象。

方案二:针对WCF代理(ClientBase)

如果是用SvcUtil.exe生成的WCF代理,可以通过实现IClientMessageInspector来拦截SOAP消息并修改XML:

  1. 创建消息检查器类:
public class RemoveEmptyTagsInspector : IClientMessageInspector
{
    public object BeforeSendRequest(ref Message request, IClientChannel channel)
    {
        // 将Message转换为XDocument
        MemoryStream ms = new MemoryStream();
        XmlWriter writer = XmlWriter.Create(ms);
        request.WriteMessage(writer);
        writer.Flush();
        ms.Position = 0;
        XDocument doc = XDocument.Load(ms);

        // 移除所有空标签
        doc.Descendants().Where(e => string.IsNullOrWhiteSpace(e.Value) && !e.HasElements).Remove();

        // 将修改后的XML转换回Message
        ms.SetLength(0);
        writer = XmlWriter.Create(ms);
        doc.Save(writer);
        writer.Flush();
        ms.Position = 0;
        XmlReader reader = XmlReader.Create(ms);
        request = Message.CreateMessage(reader, int.MaxValue, request.Version);

        return null;
    }

    public void AfterReceiveReply(ref Message reply, object correlationState)
    {
        // 无需处理响应,留空即可
    }
}
  1. 创建行为类,将检查器添加到代理行为中:
public class RemoveEmptyTagsBehavior : IEndpointBehavior
{
    public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) { }

    public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
    {
        clientRuntime.ClientMessageInspectors.Add(new RemoveEmptyTagsInspector());
    }

    public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher) { }

    public void Validate(ServiceEndpoint endpoint) { }
}
  1. 在创建代理实例时绑定该行为:
using (var client = new YourWcfProxyClient())
{
    client.Endpoint.Behaviors.Add(new RemoveEmptyTagsBehavior());
    // 调用服务方法
    client.YourServiceMethod(yourRequest);
}

额外小技巧:利用部分类避免代码覆盖

如果代理类是自动生成的,不想手动修改生成的文件,可以用**部分类(partial class)**来扩展逻辑——把重写方法或自定义行为放在单独的文件里,这样重新生成时代码不会被覆盖。

补充:如果临时需要快速生效,也可以修改生成的实体类,给字段/属性添加[XmlElement(IsNullable = false)]属性,让XmlSerializer直接跳过空标签序列化,但这种方式每次重新生成代理都要重复操作,适合短期场景。

内容的提问来源于stack exchange,提问作者Rich T.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 20:47:38