我正在尝试使用 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>
这可能吗?
我为支持正确的命名空间处理所做的更改: 添加了程序集级 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();
}
}
要测试这一点,您可以: