【问题标题】:ASP.NET WebAPI + SoapASP.NET WebAPI + 肥皂
【发布时间】:2012-07-03 19:11:04
【问题描述】:

WebAPI 是否支持 SOAP?我正在尝试在 MVC4 中编写一个 SOAP 服务器,虽然我可以在 WCF 中做到这一点,但似乎 WebAPI 正在取代它,但我看不到在其中使用 SOAP 的方法,只是使用 REST 样式接口的 JSON / XML。

【问题讨论】:

  • 如果两者兼备很重要,您可以始终使用 WCF REST 4.0 模板,并提供 POX/JSON 服务端点,并为您的 RPC 混合自定义 SOAP 端点。

标签: c# asp.net-mvc-4 asp.net-web-api


【解决方案1】:

引用 Scott Guthrie 的话:过去几年见证了 Web API 的兴起——服务通过纯 HTTP 而不是通过更正式的服务合同(如 SOAP 或 WS*)公开。

所以我会说不。

【讨论】:

  • 无赖 :(虽然这是真的,但并不是每个人都转向了 SOAP,所以互操作仍然需要 SOAP。
  • 使用 REST API 并不意味着你不能有正式的合同——比如 swagger。
  • @OndrejSvejdar 确实如此,但如果正式合同没有带来任何最终用户价值,我不会打扰。
【解决方案2】:

您应该考虑查看ServiceStack,它允许您的相同服务支持 REST + SOAP API,尽管因为 SOAP 仅适用于 HTTP POST it has some restrictions

Add ServiceStack Reference

作为 SOAP 的替代方案,ServiceStack 为 WCF 的添加服务参考提供了更好的替代方案,WCF 可以使用Add ServiceStack Reference 内置在ServiceStackVS 中的功能从 URL 生成类型化 API。

相对于 WCF 的优势

  • 简单 使用小型 T4 模板来保存生成的 POCO 类型。更新就像重新运行 T4 模板一样简单
  • 多功能 Clean DTO 适用于所有 JSON、XML、JSV、MsgPack 和 ProtoBuf generic service clients
  • 可重用 生成的 DTO 不与任何端点或格式耦合。默认值既是部分的又是虚拟的,以最大限度地重复使用
  • 弹性基于消息传递的服务提供了许多advantages over RPC Services
  • 灵活 DTO 生成可自定义,服务器和客户端可以覆盖内置默认值
  • 集成在 DTO 上注释的丰富服务元数据,Internal Services 在外部访问时被排除在外

WebAPI 和 WCF 都促进 RPC 方法签名

有趣的是,尽管 WebAPI ApiController methods 在使用 C# RPC 方法创建和定义聊天 Web 服务时采用了相同的 RPC approach as WCF,但他们仍然无法支持同一公司制定的自己的 SOAP 标准.

ServiceStack 支持具有相同服务的 REST、SOAP、HTML 和 MQ 端点

这是对 ServiceStack 的 message-based design 的证明,它提供了 numerous advantages,尽管 同一服务 无法支持多个端点和格式,包括 REST、SOAP 和 MQ 端点以及 @987654333 @如果你需要的话。这是一个丰富的Northwind database editor 示例,因为它是使用 ServiceStack 构建的,所以自动启用了一个类型化的 REST API,该 API 能够被丰富的原生桌面客户端、移动应用程序和单页应用程序调用。

SOAP 对于远程服务来说仍然是一个糟糕的选择

尽管出于互操作性、可访问性和向后兼容性的原因支持 SOAP,但我们不建议将其用于构建 Web 服务平台,因为它不必要地复杂、脆弱、缓慢和冗长,并且有更好的替代方案可供使用。我explain more in detail in my interview on InfoQ

【讨论】:

  • ServiceStack 的一个问题是操作返回类型 System.Object 使得编译时类型检查变得困难。
  • @stimpy77 这完全是可选的,您可以根据需要指定具体的返回类型。请注意,我们更喜欢在 IReturn<T> 标记上指定响应类型,以便客户端也能获得类型化的 API。
  • 这种“完全可选”的行为在 v4 中是否发生了变化,还是一直是可选的?
  • @stimpy77 New API 允许这样做,但在 v3 的原始旧 API 中不可用,因为它强制覆盖现有方法。
【解决方案3】:

WEB API 是微软对基于 REST 的 API 的回应。如果您想要 SOAP,请使用 WCF。

【讨论】:

    【解决方案4】:

    WebApi 确实不支持开箱即用的 SOAP。但它是一个非常灵活的框架,您可以“调整”它来处理 SOAP:没有什么可以阻止您手动解析接收到的 SOAP 消息(它们毕竟是纯 XML)并手动将响应生成为 XML 字符串,然后将它们与适当的内容类型标头(您甚至可以为此使用write your own content formatter)。

    根据您的需求和您现有的代码库,这可能值得付出努力,或者您可能希望使用更适合 SOAP 的技术,例如 WCF 或已经提到的 ServiceStack 框架。

    【讨论】:

    • 我最近就这样做了,并创建了自己的 SoapMessageFormatter,以便将具有 application/soap+xml 请求格式的 HTTP POST 通过管道传输到一个特殊的端点,该端点旨在解析 XML 并将其转换为 POCO,因此可以正常处理。然后结果通过相同的翻译作为响应。
    • 我在这里写了一个关于如何使用 ASP MVC 接收 SOAP 请求的答案 - stackoverflow.com/questions/27985639/…
    【解决方案5】:

    您可能想查看ServiceStack,它应该在一个界面中同时支持 SOAP 和 REST,没有任何麻烦。它声称是better match than WebAPI for web services

    我不能声称知道所有差异,但他们声称的问题是 Web API 方法固有的问题,我可以从经验中说真实的 - API 演变(在真实项目中是不可避免的) 在 web api 中相当棘手。当然,web api 不支持 SOAP。

    【讨论】:

      【解决方案6】:

      它不像 Wed API 支持 SOAP,但由于 SOAP 只是一个使用 XML 的标准,并且它传播 HTTP,您可以使用 Web API 公开一个 POST 服务来读取 XML 并使用 XPath 找到您需要的节点和然后将节点反序列化为对象。

      首先,您需要向 ConfigureServices 添加 XML 支持

      public void ConfigureServices(IServiceCollection services)
          {
      
              services.AddMvc()
                  .SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
                  .AddXmlSerializerFormatters();
          }
      

      然后在您的控制器中,您只需添加一个接收 XMLDocument 的方法,并使用 XPath 搜索您感兴趣的节点(基本上删除肥皂信封、标题、正文),然后您可以反序列化对象。 在我的例子中,我使用 WSDL 添加服务引用,然后反序列化对象。

      [HttpPost("reservationxml")]
          public void CreateReservationFromTSW(XmlDocument soapCreateReservationRq)
          {
              XmlNamespaceManager nsmgr = new XmlNamespaceManager(soapCreateReservationRq.NameTable);
              nsmgr.AddNamespace("r", "http://soa.company.com/ReservationEnt");
              nsmgr.AddNamespace("s", "http://www.w3.org/2003/05/soap-envelope");
      
              XmlNodeList xmlNodeList = soapCreateReservationRq.SelectNodes("s:Envelope/s:Body/r:CreateReservationRq",nsmgr);
              XmlNode xmlnode = xmlNodeList[0];
              XmlSerializer serial = new XmlSerializer(typeof(ServiceReference1.CreateReservationRqType));
              ServiceReference1.CreateReservationRqType rq = (ServiceReference1.CreateReservationRqType)serial.Deserialize(new XmlNodeReader(xmlnode));
      
      
          }
      

      正如您在下一张图片中看到的那样,尝试使用您的服务的服务使用带有 Accept-Encoding: gzip 的请求方法 POST。这就是为什么您可以公开可用于 SOAP 服务的 Web API。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-04-12
        • 2012-04-27
        • 2012-09-09
        • 1970-01-01
        • 2011-02-10
        • 2011-01-14
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多