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

.NET Core 9+SoapCore:移除Action节点后参数为null问题排查

SoapCore请求参数返回null问题排查与解决

问题描述

我正在学习SoapCore,希望SOAP请求的Body中直接显示函数参数,不包含Action节点。代码编写看似正确,但函数参数始终返回null。使用的是.NET Core 9搭配SoapCore,相关代码、请求及响应信息如下:

服务端代码

builder.Services.AddSoapCore();
app.UseEndpoints(endpoints =>
{
    _ = endpoints.UseSoapEndpoint<DataContractServices>("/DataContract.asmx",
        new SoapEncoderOptions(),
        SoapSerializer.DataContractSerializer);
});

[ServiceContract(Namespace = "https://service.com/")]
public class DataContractServices
{
    [OperationContract(Name = "loginMethod")]
    public string LoginMethod(LoginRequest input)
        => $"Username: {input.Username}| Password: {input.Password}";
}

[MessageContract(IsWrapped = true, WrapperName = "LoginRequest", WrapperNamespace = "https://service.com/")]
public class LoginRequest
{
    [MessageBodyMember(Name = "username")]
    public string Username { get; set; } = string.Empty;
    [MessageBodyMember(Name = "password")]
    public string Password { get; set; } = string.Empty;
}

请求内容

POST http://localhost:5000/DataContract.asmx
Content-Type: text/xml; charset=utf-8
SOAPAction: https://service.com/loginMethod

<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:pay="https://service.com/">
   <soapenv:Header/>
   <soapenv:Body>
      <pay:LoginRequest>
        <pay:username>myUsername</pay:username>
        <pay:password>myPassword</pay:password>
      </pay:LoginRequest>
   </soapenv:Body>
</soapenv:Envelope>

响应内容

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <s:Body>
    <loginMethodResponse xmlns="https://service.com/">
      <loginMethodResult>Username: | Password:</loginMethodResult>
    </loginMethodResponse>
  </s:Body>
</s:Envelope>

问题根源

请求中的username和password元素通过pay前缀关联到https://service.com/命名空间,但代码中MessageBodyMember属性未指定对应命名空间,默认使用空命名空间,导致DataContractSerializer无法匹配请求中的元素,最终参数值为null。

解决方法

方案一:为MessageBodyMember指定命名空间

修改LoginRequest类的属性,给每个MessageBodyMember添加命名空间配置,与请求中的命名空间保持一致:

[MessageContract(IsWrapped = true, WrapperName = "LoginRequest", WrapperNamespace = "https://service.com/")]
public class LoginRequest
{
    [MessageBodyMember(Name = "username", Namespace = "https://service.com/")]
    public string Username { get; set; } = string.Empty;
    [MessageBodyMember(Name = "password", Namespace = "https://service.com/")]
    public string Password { get; set; } = string.Empty;
}

方案二:修改请求,移除子元素的命名空间前缀

如果希望参数元素不使用命名空间,调整请求XML,去掉username和password的pay前缀:

<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:pay="https://service.com/">
   <soapenv:Header/>
   <soapenv:Body>
      <pay:LoginRequest>
        <username>myUsername</username>
        <password>myPassword</password>
      </pay:LoginRequest>
   </soapenv:Body>
</soapenv:Envelope>

扩展:实现Body直接显示参数(无Wrapper)

如果要实现请求Body中直接显示参数、不包含Wrapper节点,可修改MessageContract的IsWrapped为false,同时调整代码和请求:

修改后的LoginRequest类

[MessageContract(IsWrapped = false)]
public class LoginRequest
{
    [MessageBodyMember(Name = "username", Namespace = "https://service.com/")]
    public string Username { get; set; } = string.Empty;
    [MessageBodyMember(Name = "password", Namespace = "https://service.com/")]
    public string Password { get; set; } = string.Empty;
}

对应的请求XML

<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:pay="https://service.com/">
   <soapenv:Header/>
   <soapenv:Body>
        <pay:username>myUsername</pay:username>
        <pay:password>myPassword</pay:password>
   </soapenv:Body>
</soapenv:Envelope>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 09:33:19