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

移除手动WSDL包装标签,CoreWCF端点匹配旧WSDL配置问题

解决CoreWCF中SOAP端点匹配旧WSDL的问题

需将旧.NET 4.7应用升级到.NET Core,用CoreWCF重新实现SOAP端点,必须严格匹配客户端使用的旧WSDL。VS导入旧WSDL时因依赖ServiceModel无法直接使用,修改引用后OperationContract输入参数始终为空,故手动定义服务契约、操作契约及数据成员,但生成的XML结构与旧WSDL不符。

客户端发送的目标XML结构

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://www.test.me/method/">
    <SOAP-ENV:Body>
        <ns1:method1>
            <msgContBody>
                <par1>Hello</par1>
                <descPar1>Desc of Hello</descPar1>
                <par2>World</par2>
                <descPar2>Desc of World</descPar2>
                <arrayPar>
                    <Id>1</Id>
                    <Desc>one</Desc>
                </arrayPar>
                <arrayPar>
                    <Id>2</Id>
                    <Desc>two</Desc>
                </arrayPar>
                <arrayPar>
                    <Id>3</Id>
                    <Desc>three</Desc>
                </arrayPar>
            </msgContBody>
        </ns1:method1>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

当前生成的不符合结构的XML

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://www.test.me/method/">
   <soapenv:Header/>
   <soapenv:Body>
      <ns1:method1>
         <!--Optional:-->
         <ns1:request>
            <!--Zero or more repetitions:-->
            <rootPar>
               <!--Optional:-->
               <par1>?</par1>
               <!--Optional:-->
               <descPar1>?</descPar1>
               <!--Optional:-->
               <par2>?</par2>
               <!--Optional:-->
               <descPar2>?</descPar2>
               <!--Optional:-->
               <arrayPar>
               <!--Zero or more repetitions:-->
                    <arrayPar>
                        <!--Optional:-->
                        <Id>1</Id>
                        <!--Optional:-->
                        <Desc>one</Desc>
                    </arrayPar>
                    <arrayPar>
                        <!--Optional:-->
                        <Id>2</Id>
                        <!--Optional:-->
                        <Desc>two</Desc>
                    </arrayPar>
                    <arrayPar>
                        <!--Optional:-->
                        <Id>3</Id>
                        <!--Optional:-->
                        <Desc>three</Desc>
                    </arrayPar>
               </arrayPar>
            </rootPar>
         </ns1:request>
      </ns1:method1>
   </soapenv:Body>
</soapenv:Envelope>

需要修正的问题

  • 移除多余的request包装标签
  • 移除arrayPar的外层包装标签,直接生成多个<arrayPar>元素

当前代码实现

[ServiceContract(Namespace = "http://www.test.me/method/")]
public interface IMeService
{
    [OperationContract]
    Task<myResponse> method1Async(myRequest request);
}

public class MeService: IMeService
{
    public async Task<myResponse> method1Async(myRequest request)
    {
        // 业务逻辑实现
        return await Task.FromResult(new myResponse());
    }
}

[MessageContract(WrapperNamespace = "http://www.test.me/method/", WrapperName = "method1")]
public class myRequest
{
    [MessageBodyMember(Name = "rootPar")]
    public rootPar[] rootPar;
}

[DataContract(Namespace = "")]
public class rootPar
{
    [DataMember(Name = "par1")]
    public string par1{ get; set; }

    [DataMember(Name = "descPar1")]
    public string descPar1{ get; set; }

    [DataMember(Name="par2")]
    public string par2{ get; set; }

    [DataMember(Name = "descPar2")]
    public string descPar2{ get; set; }

    [DataMember]
    public arrPar[] arrPar{ get; set; }
}

[DataContract(Namespace = "")]
public class arrPar
{
    [DataMember(Name="Id")]
    public string Id{ get; set; }

    [DataMember(Name = "Desc")]
    public string Desc{ get; set; }
}

// 补充定义myResponse
[MessageContract(WrapperNamespace = "http://www.test.me/method/", WrapperName = "method1Response")]
public class myResponse
{
    // 根据旧WSDL定义响应结构
    [MessageBodyMember(Name = "result")]
    public string Result { get; set; }
}

修正后的代码实现

[ServiceContract(Namespace = "http://www.test.me/method/")]
public interface IMeService
{
    [OperationContract]
    Task<myResponse> method1Async(myRequest request);
}

public class MeService: IMeService
{
    public async Task<myResponse> method1Async(myRequest request)
    {
        // 业务逻辑实现,此时request.MsgContBody可正确接收客户端参数
        return await Task.FromResult(new myResponse());
    }
}

// 匹配客户端的method1包裹结构,直接将msgContBody作为消息体成员
[MessageContract(WrapperNamespace = "http://www.test.me/method/", WrapperName = "method1")]
public class myRequest
{
    // Name对应客户端的msgContBody标签,类型为单个rootPar(客户端中是单个msgContBody节点)
    [MessageBodyMember(Name = "msgContBody", Namespace = "")]
    public rootPar MsgContBody;
}

[DataContract(Namespace = "")]
public class rootPar
{
    [DataMember(Name = "par1", Order = 1)]
    public string Par1 { get; set; }

    [DataMember(Name = "descPar1", Order = 2)]
    public string DescPar1 { get; set; }

    [DataMember(Name = "par2", Order = 3)]
    public string Par2 { get; set; }

    [DataMember(Name = "descPar2", Order = 4)]
    public string DescPar2 { get; set; }

    // 指定DataMember的Name为arrayPar,序列化时直接生成多个<arrayPar>节点,无需外层包装
    [DataMember(Name = "arrayPar", Order = 5, IsRequired = false)]
    public arrPar[] ArrayPar { get; set; }
}

[DataContract(Namespace = "")]
public class arrPar
{
    [DataMember(Name = "Id", Order = 1)]
    public string Id { get; set; }

    [DataMember(Name = "Desc", Order = 2)]
    public string Desc { get; set; }
}

// 响应契约同样匹配旧WSDL结构
[MessageContract(WrapperNamespace = "http://www.test.me/method/", WrapperName = "method1Response")]
public class myResponse
{
    [MessageBodyMember(Name = "msgContBodyResponse", Namespace = "")]
    public rootResponse ResponseBody { get; set; }
}

[DataContract(Namespace = "")]
public class rootResponse
{
    // 根据旧WSDL定义响应字段
    [DataMember(Name = "code")]
    public string Code { get; set; }

    [DataMember(Name = "message")]
    public string Message { get; set; }
}

关键修正点说明

  1. MessageContract调整:将myRequest的MessageBodyMember名称改为msgContBody,与客户端XML节点名一致,且类型设为单个rootPar(客户端中msgContBody是单个节点,而非数组)。
  2. 数组字段修正:rootPar中的数组字段ArrayPar,通过[DataMember(Name = "arrayPar")]指定序列化后的节点名,这样CoreWCF会直接生成多个<arrayPar>节点,不会额外添加外层包装。
  3. 命名空间与顺序:所有数据契约的Namespace设为空,与客户端XML中的非命名空间节点匹配;添加Order属性确保节点顺序与旧WSDL一致。
  4. 参数接收验证:修正后客户端发送的XML会正确绑定到request.MsgContBody,不会出现参数为空的问题。

内容的提问来源于stack exchange,提问作者dpope

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 15:47:08