【问题标题】:Implement SOAP 1.2 service in asp.net core在 asp.net core 中实现 SOAP 1.2 服务
【发布时间】:2019-08-07 07:54:02
【问题描述】:

我正在尝试在 ASP.Net Core 2.2 下实现 OCPP 1.5。该标准使用 SOAP 1.2。问题来自对MessageHeader 属性的错误解释。带有MessageHeader 的属性应该在标题中,但它们不是。

源码:https://github.com/delianenchev/OcppDemo

我在 ASP.Net Core 下使用 SoapCore。我的初始化如下所示:

        var transportBinding = new HttpTransportBindingElement();
        var textEncodingBinding = new TextMessageEncodingBindingElement(MessageVersion.Soap12WSAddressingAugust2004, System.Text.Encoding.UTF8);
        var customBinding = new CustomBinding(transportBinding, textEncodingBinding);
        app.UseSoapEndpoint<ISampleService>("/SOAP/service.wsdl", customBinding, SoapSerializer.DataContractSerializer);

我的演示模型具有MessageHeaderMessageBodyMember 属性。

[MessageContract]
public class MessageModelRequest
{
    [MessageHeader]
    public string Id { get; set; }

    [MessageBodyMember]
    public string Name { get; set; }

    [MessageBodyMember]
    public string Email { get; set; }
}

我使用 SoapUI 测试 API。

这是我在 ASP.NET 核心下使用 SoapCore 的 API。

<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:tem="http://tempuri.org/" xmlns:mod="http://schemas.datacontract.org/2004/07/Models">
   <soap:Header/>
   <soap:Body>
      <tem:TestMessageModel>
         <!--Optional:-->
         <tem:inputModel>
            <!--Optional:-->
            <mod:Email>?</mod:Email>
            <!--Optional:-->
            <mod:Id>1</mod:Id>
            <!--Optional:-->
            <mod:Name>?</mod:Name>
         </tem:inputModel>
      </tem:TestMessageModel>
   </soap:Body>
</soap:Envelope>

WCF 项目中用于 IIS 的正确 API。

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tem="http://tempuri.org/">
   <soapenv:Header>
      <tem:Id>34</tem:Id>
   </soapenv:Header>
   <soapenv:Body>
      <tem:MessageModelRequest>
         <!--Optional:-->
         <tem:Email>3</tem:Email>
         <!--Optional:-->
         <tem:Name>4</tem:Name>
      </tem:MessageModelRequest>
   </soapenv:Body>
</soapenv:Envelope>

【问题讨论】:

    标签: c# wcf asp.net-core soap


    【解决方案1】:

    好吧,从SoapCore 的源代码来看,它似乎支持用于读取 SOAP 消息的消息头,因为它使用MessageEncoder 来达到这个目的,它确切地知道如何读取 SOAP 消息,但是当涉及到序列化时在您的情况下,uses a native DataContractSerializer 的响应用于编写忽略您在班级中拥有的任何消息合同属性的正文,而且它没有任何用于编写标头的部分,只有消息正文。

    所以我猜你需要自己在响应消息中实现标头支持。

    首先,在要添加到响应消息头的属性上添加IgnoreMemberAttribute(或XmlIgnoreAttribute,如果您切换到SoapSerializer.XmlSerializer),这样数据协定序列化程序就不会将它们添加到消息。

    最后,您需要手动定位带有MessageHeader 属性的属性并将它们添加到您的标题中。幸运的是,SoapCore 有多种选择,例如suggested here。 作为替代方案,如果您计划在您的解决方案中包含SoapCore 的来源,您可以在these lines 的某个地方轻松实现目标。这样做很容易,因为在这个地方,您可以完全控制消息以及您从服务方法获得的响应。借助反射,您可以轻松找到responseObject 需要移动到表头的属性,然后将它们转发到responseMessage.Headers

    我知道这有点讨厌,但是……这就是在 .NET Core 中使用 SOAP 的代价。

    【讨论】:

      【解决方案2】:

      .NET 6 中,例如,您可以执行以下操作以切换到 SOAP 1.2(又名soap12):

      // In Program.cs ...
      var builder = WebApplication.CreateBuilder(args);
      var app = builder.Build();
      // ...
      app.UseSoapEndpoint<IMyServiceContract>("/MyService.asmx", new SoapEncoderOptions()
      {
          // Use SOAP version 1.2 (aka Soap12)
          MessageVersion = MessageVersion.Soap12WSAddressingAugust2004
          // - OR -
          MessageVersion = MessageVersion.Soap12WSAddressing10
      }, caseInsensitivePath: true);
      

      这将导致:

      <wsdl:definitions xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" ...>
      

      【讨论】:

        猜你喜欢
        • 2011-02-08
        • 2019-06-06
        • 2019-03-09
        • 2018-07-15
        • 1970-01-01
        • 1970-01-01
        • 2020-05-19
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多