这与 OP 可能打算询问的情况略有不同,但更广泛地解释了“如何像 WCF 服务那样为我的 API 创建类似 WSDL 的东西?”
我遇到了一种情况,我们无法公开 WCF 服务,唯一的选择是 WebAPI。然而,使用 API 的一方只支持 SOAP/WSDL,并且有一个预定义的 WSDL,他们需要集成商来托管和遵守。
提供 WSDL 文件
一个 WebAPI 操作为 WSDL 文件提供服务,该文件只是一个静态 WSDL 文件。此方法不支持查询部分 WSDL。因此客户端必须使用 URL 请求yourdomain.com/SomeRoot/SomeApiPath?wsdl,之后的任何查询字符串参数都将被忽略,并提供完整的 WSDL。参数[FromUri] string wsdl 确保为包含?wsdl 的URL 选择此操作,但其中没有任何值。
public IHttpActionResult SomeApiPath([FromUri] string wsdl)
{
System.IO.FileStream wsdlFileStream = System.IO.File.OpenRead(System.Web.HttpContext.Current.Server.MapPath("~/Content/SomeThing.wsdl"));
var response = new HttpResponseMessage(HttpStatusCode.OK);
response.Content = new StreamContent(wsdlFileStream);
response.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("text/xml");
return ResponseMessage(response);
}
这意味着您的 API 操作方法需要处理和响应 XML SOAP 请求。
处理 SOAP 请求
虽然 WebAPI 可以将参数绑定到 XML 请求,但我选择在操作中不使用参数,而是在每个操作中使用 Request.Content.ReadAsStringAsync() 来获取请求正文(即 XML SOAP 请求),然后使用 XML 对其进行解析到 LINQ 以获取我需要的特定值。这使我免于尝试对 XML 可序列化 POCO 进行逆向工程以匹配 WSDL 定义的请求结构。
创建 SOAP 响应
您可以在 Visual Studio 中使用 Svcutil.exe 等工具来生成 XML 可序列化 POCO。由于我们不使用 WCF,因此您不会使用完整的服务合同,而只需提取 C# 类 POCO,以便您可以使用数据填充它们并将它们序列化为 XML 以创建响应。但是,创建具有所有正确名称空间引用的 SOAP 信封极具挑战性。我在某些地方进行了修改,实际上使用了字符串连接而不是 XML 序列化。序列化为 XML 字符串,并在 StringContent 响应中返回:
return ResponseMessage(
new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new StringContent(soapResponseBody, System.Text.Encoding.UTF8, "text/xml")
});
注意:即使是异常也必须被捕获并转换为 XML 作为 SOAP 信封内的 SOAP 错误。
以上所有可怕的变通方法都证明,如果您绝对必须支持 SOAP,那么使用 WebAPI 以外的任何东西都会容易得多。我喜欢 WebAPI,但是当您必须与另一个系统集成时只支持 SOAP/WSDL,它肯定不是工作的工具。 我提供以上内容作为在您别无选择时解决此问题的方法的摘要,但建议使用除 WebAPI 之外的支持 SOAP 的框架。您肯定会遇到问题以上,并且需要有大量的 XML 序列化和 XML 模式经验才能理解如何解决这些问题。
拥有预定义 WSDL 并要求其他人实现公开该 WSDL 的服务也很奇怪/很少见。换句话说,他们作为客户端从他们这边集成,而您是主机,但他们决定了请求的结构。通常情况正好相反,有人使用预定义的 WSDL 公开了一个服务,而您必须实现一个客户端来使用它,这通常要容易得多。