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

如何在ASP.NET Core控制器中调用SOAP服务及解决WSDL报错

在ASP.NET Core 8中调用SOAP服务的TOOTREG方法及WSDL生成错误修复

问题背景

我基于C#开发ASP.NET Core 8 Web API项目,需要通过HTTPS调用外部SOAP服务的TOOTREG方法。该SOAP服务的WSDL地址为:https://ncfailid.emta.ee/index.php/s/wTKjgm9QQnWLZEH/download/tor.wsdl.txt,其中TOOTREG方法的定义如下:

<element name="TOOTREG">
  <complexType>
    <sequence>
      <element name="request" type="tns:tootregRequestType"/>
    </sequence>
  </complexType>
</element>
<element name="TOOTREGResponse">
  <complexType>
    <sequence>
      <element name="request" type="tns:tootregRequestType"/>
      <element name="response" type="tns:tootregResponseType"/>
    </sequence>
  </complexType>
</element>

请求体tns:tootregRequestType和响应类型均为WSDL中定义的复杂类型。尝试通过Visual Studio社区版的「添加服务引用」功能生成客户端代码时,出现以下错误:

未处理来自命名空间'http://x-road.eu/xsd/xroad.xsd'的可选WSDL扩展元素'address'。
XPath: //wsdl:definitions[@targetNamespace='http://emta-v6.x-road.eu']/wsdl:service[@name='TorServiceV6']/wsdl:port[@name='TorV6WebServiceImpl']
未处理来自命名空间'http://x-road.eu/xsd/xroad.xsd'的可选WSDL扩展元素'title'。
XPath: //wsdl:definitions[@targetNamespace='http://emta-v6.x-road.eu']/wsdl:service[@name='TorServiceV6']/wsdl:port[@name='TorV6WebServiceImpl']
未处理来自命名空间'http://x-road.eu/xsd/xroad.xsd'的可选WSDL扩展元素'version'。
XPath: //wsdl:definitions[@targetNamespace='http://emta-v6.x-road.eu']/wsdl:binding[@name='TorPortBinding']/wsdl:operation[@name='TORTI']
未处理来自命名空间'http://x-road.eu/xsd/xroad.xsd'的可选WSDL扩展元素'version'。
XPath: //wsdl:definitions[@targetNamespace='http://emta-v6.x-road.eu']/wsdl:binding[@name='TorPortBinding']/wsdl:operation[@name='TORSPORT']
未处理来自命名空间'http://x-road.eu/xsd/xroad.xsd'的可选WSDL扩展元素'version'。
XPath: //wsdl:definitions[@targetNamespace='http://emta-v6.x-road.eu']/wsdl:binding[@name='TorPortBinding']/wsdl:operation[@name='TORT']
未处理来自命名空间'http://x-road.eu/xsd/xroad.xsd'的可选WSDL扩展元素'version'。
XPath: //wsdl:definitions[@targetNamespace='http://emta-v6.x-road.eu']/wsdl:binding[@name='TorPortBinding']/wsdl:operation[@name='TORRKA']
未处理来自命名空间'http://x-road.eu/xsd/xroad.xsd'的可选WSDL扩展元素'version'。
XPath: //wsdl:definitions[@targetNamespace='http://emta-v6.x-road.eu']/wsdl:binding[@name='TorPortBinding']/wsdl:operation[@name='TORINFO']
未处理来自命名空间'http://x-road.eu/xsd/xroad.xsd'的可选WSDL扩展元素'version'。
XPath: //wsdl:definitions[@targetNamespace='http://emta-v6.x-road.eu']/wsdl:binding[@name='TorPortBinding']/wsdl:operation[@name='TORIK']
未处理来自命名空间'http://x-road.eu/xsd/xroad.xsd'的可选WSDL扩展元素'version'。
XPath: //wsdl:definitions[@targetNamespace='http://emta-v6.x-road.eu']/wsdl:binding[@name='TorPortBinding']/wsdl:operation[@name='TOOTREG']
未处理来自命名空间'http://x-road.eu/xsd/xroad.xsd'的可选WSDL扩展元素'requirecontent'。
XPath: //wsdl:definitions[@targetNamespace='http://emta-v6.x-road.eu']/wsdl:binding[@name='TorPortBinding']/wsdl:operation[@name='TOOTREG_AMETNIK']
未处理来自命名空间'http://x-road.eu/xsd/xroad.xsd'的可选WSDL扩展元素'version'。
XPath: //wsdl:definitions[@targetNamespace='http://emta-v6.x-road.eu']/wsdl:binding[@name='TorPortBinding']/wsdl:operation[@name='TOOTREG_AMETNIK']
未处理来自命名空间'http://x-road.eu/xsd/xroad.xsd'的可选WSDL扩展元素'requirecontent'。
XPath: //wsdl:definitions[@targetNamespace='http://emta-v6.x-road.eu']/wsdl:binding[@name='TorPortBinding']/wsdl:operation[@name='TORRGNO']
未处理来自命名空间'http://x-road.eu/xsd/xroad.xsd'的可选WSDL扩展元素'version'。
XPath: //wsdl:definitions[@targetNamespace='http://emta-v6.x-road.eu']/wsdl:binding[@name='TorPortBinding']/wsdl:operation[@name='TORRGNO']
未处理来自命名空间'http://x-road.eu/xsd/xroad.xsd'的可选WSDL扩展元素'requirecontent'。
XPath: //wsdl:definitions[@targetNamespace='http://emta-v6.x-road.eu']/wsdl:binding[@name='TorPortBinding']/wsdl:operation[@name='TORSYNK']
未处理来自命名空间'http://x-road.eu/xsd/xroad.xsd'的可选WSDL扩展元素'version'。
XPath: //wsdl:definitions[@targetNamespace='http://emta-v6.x-road.eu']/wsdl:binding[@name='TorPortBinding']/wsdl:operation[@name='TORSYNK']
未处理来自命名空间'http://x-road.eu/xsd/xroad.xsd'的可选WSDL扩展元素'requirecontent'。
XPath: //wsdl:definitions[@targetNamespace='http://emta-v6.x-road.eu']/wsdl:binding[@name='TorPortBinding']/wsdl:operation[@name='TORKODAK']
未处理来自命名空间'http://x-road.eu/xsd/xroad.xsd'的可选WSDL扩展元素'version'。
XPath: //wsdl:definitions[@targetNamespace='http://emta-v6.x-road.eu']/wsdl:binding[@name='TorPortBinding']/wsdl:operation[@name='TORKODAK']
导出期间生成的架构存在验证错误:
    来源:
    行:13 列:3
   验证错误:属性组'http://www.w3.org/XML/1998/namespace:specialAttrs'已声明。
导出期间生成的架构存在验证错误:
    来源:
    行:12 列:3
   验证错误:全局属性'http://www.w3.org/XML/1998/namespace:id'已声明。
导出期间生成的架构存在验证错误:
    来源:
    行:11 列:3
   验证错误:全局属性'http://www.w3.org/XML/1998/namespace:base'已声明。
导出期间生成的架构存在验证错误:
    来源:
    行:3 列:3
   验证错误:全局属性'http://www.w3.org/XML/1998/namespace:space'已声明。
导出期间生成的架构存在验证错误:
    来源:
    行:2 列:3
   验证错误:全局属性'http://www.w3.org/XML/1998/namespace:lang'已声明。

错误原因分析

这些错误分为两类:

  1. X-Road扩展元素不支持:Visual Studio的服务引用工具无法识别http://x-road.eu/xsd/xroad.xsd命名空间下的自定义WSDL扩展(如address、title、version等)。
  2. XML标准命名空间属性重复声明:WSDL中重复引入了http://www.w3.org/XML/1998/namespace下的属性,导致架构验证时出现重复定义错误。

修复方案

方案一:修改WSDL后自动生成客户端代码

通过手动修改WSDL移除不兼容元素,再用工具生成代码:

  1. 下载WSDL到本地:访问上述WSDL地址,将内容保存为本地文件(如tor-modified.wsdl)。
  2. 移除X-Road扩展元素:打开本地WSDL文件,删除所有属于http://x-road.eu/xsd/xroad.xsd命名空间的节点(例如<xroad:address>、<xroad:version>等)。
  3. 解决重复属性声明:找到WSDL中重复定义http://www.w3.org/XML/1998/namespace属性的部分,仅保留一处声明,删除其余重复的属性组或属性定义。
  4. 生成客户端代码:
    • Visual Studio图形界面:右键项目 → 添加 → 服务引用 → 高级 → 添加Web引用,选择本地修改后的WSDL文件;
    • SvcUtil命令行工具:执行以下命令生成代码:
      svcutil.exe "C:\path\to\tor-modified.wsdl" /out:TorServiceClient.cs /namespace:YourProject.TorService
      
  5. 在API控制器中使用生成的代码:
    [ApiController]
    [Route("api/tor")]
    public class TorApiController : ControllerBase
    {
        [HttpPost("tootreg")]
        public async Task<IActionResult> InvokeTootreg(TootregRequestType request)
        {
            using var client = new TorServiceV6Client();
            // 替换为实际SOAP服务的Endpoint地址
            client.Endpoint.Address = new EndpointAddress("https://实际SOAP服务地址");
            
            var response = await client.TOOTREGAsync(new TOOTREG { request = request });
            return Ok(response.response);
        }
    }
    

方案二:手动构造SOAP请求(无需代码生成)

若修改WSDL过于繁琐,可直接通过HttpClient手动发送SOAP请求:

  1. 手动定义模型类:根据WSDL中的tns:tootregRequestType和tns:tootregResponseType结构,创建对应的C#模型:
    public class TootregRequest
    {
        // 按WSDL定义的字段添加属性,示例:
        public string RegNumber { get; set; }
        public string Name { get; set; }
    }
    
    public class TootregResponse
    {
        // 对应响应字段,示例:
        public string StatusCode { get; set; }
        public string StatusMessage { get; set; }
        // 其他复杂类型字段按需添加
    }
    
  2. 在API控制器中发送请求并解析响应:
    [ApiController]
    [Route("api/tor")]
    public class TorApiController : ControllerBase
    {
        private readonly HttpClient _httpClient;
    
        public TorApiController(HttpClient httpClient)
        {
            _httpClient = httpClient;
        }
    
        [HttpPost("tootreg")]
        public async Task<IActionResult> CallTootreg(TootregRequest request)
        {
            // 构造SOAP信封XML
            var soapXml = $@"<?xml version=""1.0"" encoding=""utf-8""?>
    

<soapenv:Envelope xmlns:soapenv=""http://schemas.xmlsoap.org/soap/envelope/"" xmlns:emta=""http://emta-v6.x-road.eu"">
soapenv:Header/
soapenv:Body
emta:TOOTREG
emta:request
emta:regNumber{request.RegNumber}</emta:regNumber>
emta:name{request.Name}</emta:name>
</emta:request>
</emta:TOOTREG>
</soapenv:Body>
</soapenv:Envelope>";

var content = new StringContent(soapXml, Encoding.UTF8, "text/xml");
       content.Headers.Add("SOAPAction", "http://emta-v6.x-road.eu/TOOTREG");

       var httpResponse = await _httpClient.PostAsync("https://实际SOAP服务地址", content);
       httpResponse.EnsureSuccessStatusCode();

       var responseXml = await httpResponse.Content.ReadAsStringAsync();
       // 使用XmlSerializer解析响应
       var serializer = new XmlSerializer(typeof(TootregResponse), new XmlRootAttribute("response"));
       using var reader = new StringReader(responseXml);
       var result = (TootregResponse)serializer.Deserialize(reader);

       return Ok(result);
   }

}

注意:需根据WSDL中实际的字段结构调整XML内容和模型类属性。

内容的提问来源于stack exchange,提问作者Andrus
相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 01:10:55