使用 SoapCore 时如何在 WSDL 中拥有命名空间

问题描述 投票:0回答:1

我正在尝试使用 ASP.NET Core 服务中的 SoapCore 库提供一个 SOAP 端点,其中返回类型的主体具有特定的命名空间。 无论我做什么,生成的 WSDL 似乎都缺少我在 XML 契约中定义的名称空间。

在 Program.cs 中,我定义了 SOAP 端点:

(app as IApplicationBuilder).UseSoapEndpoint(typeof(IDummyService),
(opt) =>
{
    opt.Path = "/DummyService.svc";
    opt.Binding = new BasicHttpBinding();
    opt.SoapSerializer = SoapSerializer.XmlSerializer;
});

其中 IDummyService 定义为

[ServiceContract(Namespace = "DummyServiceNamespace")]
public interface IDummyService
{
   [OperationContract]
   DummyDataResponse GetDummyData();
}

类型定义为:

[XmlType("DummyDataResponse")]
[XmlRoot("DummyDataResponse")]
public class DummyDataResponse
{
    [XmlElement(Form = XmlSchemaForm.Qualified, Namespace = "http://www.ech.ch/xmlns/eCH-0020-f/3", Order = 0)]
    public DeliveryType Delivery { get; set; }
}

还有

[Serializable]
[XmlType("deliveryType", Namespace="http://www.ech.ch/xmlns/eCH-0020-f/3")]
public class DeliveryType
{
    [XmlAttribute(AttributeName = "Test")]
    public string Test { get; set; }
}

这将为我提供一个如下所示的 WSDL:

<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="DummyServiceNamespace" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:http="http://schemas.microsoft.com/ws/06/2004/policy/http" xmlns:msc="http://schemas.microsoft.com/ws/2005/12/wsdl/contract" xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" targetNamespace="DummyServiceNamespace" name="IDummyService">
<wsdl:types>
<xsd:schema elementFormDefault="qualified" targetNamespace="DummyServiceNamespace">
<xsd:element name="GetDummyData">
<xsd:complexType/>
</xsd:element>
<xsd:element name="GetDummyDataResponse">
<xsd:complexType>
<xsd:sequence>
<xsd:element minOccurs="0" maxOccurs="1" name="DummyDataResponse" type="tns:DummyDataResponse"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:complexType name="DummyDataResponse">
<xsd:sequence>
<xsd:element minOccurs="0" maxOccurs="1" name="Delivery" type="tns:deliveryType"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="deliveryType">
<xsd:attribute name="Test" type="xsd:string"/>
</xsd:complexType>
</xsd:schema>
</wsdl:types>
<wsdl:message name="IDummyService_GetDummyData_InputMessage">
<wsdl:part name="parameters" element="tns:GetDummyData"/>
</wsdl:message>
<wsdl:message name="IDummyService_GetDummyData_OutputMessage">
<wsdl:part name="parameters" element="tns:GetDummyDataResponse"/>
</wsdl:message>
<wsdl:portType name="IDummyService">
<wsdl:operation name="GetDummyData">
<wsdl:input message="tns:IDummyService_GetDummyData_InputMessage"/>
<wsdl:output message="tns:IDummyService_GetDummyData_OutputMessage"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="BasicHttpBinding_IDummyService_soap" type="tns:IDummyService">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="GetDummyData">
<soap:operation soapAction="DummyServiceNamespace/IDummyService/GetDummyData" style="document"/>
<wsdl:input>
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output>
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="IDummyService">
<wsdl:port name="BasicHttpBinding_IDummyService_soap" binding="tns:BasicHttpBinding_IDummyService_soap">
<soap:address location="http://localhost:5058/DummyService.svc"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>

现在我真正想要(和期望)的是一个 WSDL,其中 DeliveryType 实际上有一个自己的模式,目标名称空间为 ech20:http://www.ech.ch/xmlns/eCH-0020-f/3 。所以,像这样:

<xs:schema attributeFormDefault="unqualified"
               elementFormDefault="qualified"
               targetNamespace="http://www.ech.ch/xmlns/eCH-0020-f/3"
               version="3.0"
               xmlns:xs="http://www.w3.org/2001/XMLSchema"
               xmlns:ech20="http://www.ech.ch/xmlns/eCH-0020-f/3">

       <xsd:complexType name="deliveryType">
           <xsd:attribute name="Test" type="xsd:string"/>
       </xsd:complexType>
</schema>

这可能吗?

.net-core wsdl soapcore
1个回答
0
投票

我为支持正确的命名空间处理所做的更改: 添加了程序集级 ContractNamespace 属性,以将 XML 命名空间映射到 CLR 命名空间。 修改服务合约以使用正确的服务命名空间:

[ServiceContract(Namespace = "http://services.example.com")]

向响应类型添加了显式名称空间声明:

[XmlType(Namespace = "http://services.example.com")]

使用适当的 XML 序列化属性和命名空间规范:

[XmlElement(ElementName = "delivery", 
       Form = XmlSchemaForm.Qualified, 
       Namespace = "http://www.ech.ch/xmlns/eCH-0020-f/3")]

更新了 SOAP 端点配置以使用正确的编码选项。

当您运行此服务时,生成的 WSDL 将包含命名空间的单独架构定义。 DeliveryType 将在

http://www.ech.ch/xmlns/eCH-0020-f/3.

下正确命名
using System;
using System.ServiceModel;
using System.Xml.Schema;
using System.Xml.Serialization;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using SoapCore;
using System.Runtime.Serialization;

// Define XML namespaces
[assembly: ContractNamespace("http://www.ech.ch/xmlns/eCH-0020-f/3",
    ClrNamespace = "YourNamespace.Contracts.ECH020")]

namespace YourNamespace
{
    // Service Contract
    [ServiceContract(Namespace = "http://services.example.com")]
    public interface IDummyService
    {
        [OperationContract]
        [XmlSerializerFormat]
        DummyDataResponse GetDummyData();
    }

    // Service Implementation
    public class DummyService : IDummyService
    {
        public DummyDataResponse GetDummyData()
        {
            return new DummyDataResponse
            {
                Delivery = new DeliveryType { Test = "test" }
            };
        }
    }

    // Response Types
    [XmlType(Namespace = "http://services.example.com")]
    public class DummyDataResponse
    {
        [XmlElement(ElementName = "delivery", 
                   Form = XmlSchemaForm.Qualified, 
                   Namespace = "http://www.ech.ch/xmlns/eCH-0020-f/3")]
        public DeliveryType Delivery { get; set; }
    }

    [XmlType(TypeName = "deliveryType", 
             Namespace = "http://www.ech.ch/xmlns/eCH-0020-f/3")]
    public class DeliveryType
    {
        [XmlAttribute("test")]
        public string Test { get; set; }
    }
}

// Program.cs configuration
public class Program
{
    public static void Main(string[] args)
    {
        var builder = WebApplication.CreateBuilder(args);
        
        // Add services
        builder.Services.AddSoapCore();
        builder.Services.AddScoped<IDummyService, DummyService>();

        var app = builder.Build();

        // Configure SOAP endpoint
        app.UseSoapEndpoint<IDummyService>("/DummyService.svc", new SoapEncoderOptions
        {
            MessageVersion = System.ServiceModel.Channels.MessageVersion.Soap11,
            WriteEncoding = System.Text.Encoding.UTF8,
            ReaderQuotas = new System.Xml.XmlDictionaryReaderQuotas
            {
                MaxStringContentLength = 1048576
            }
        }, 
        SoapSerializer.XmlSerializer,
        true,
        null,
        null,
        true);

        app.Run();
    }
}

要测试这一点,您可以:

  • 运行服务
  • 访问 WSDL:http://localhost:5058/DummyService.svc?wsdl
  • 验证架构是否正确分隔并命名空间
© www.soinside.com 2019 - 2024. All rights reserved.