是否可以使用 mvc 对 soap 请求进行建模?

Is it possible to model bind a soap request with mvc?

一个客户端有一个服务发送 xml soap 格式的请求,我们需要通过我们的 .Net MVC4 项目接收这些请求。请求的格式为:

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <soap:Body>
        <ReceiveStatusUpdate xmlns="http://test.com">
            <StatusUpdate>
                <Reference>214563</Reference>
                <ThirdPartyReference>YOUR-REFERENCE</ThirdPartyReference>
                <Status>Pending</Status>
            </StatusUpdate>
        </ReceiveStatusUpdate>
    </soap:Body>
</soap:Envelope>

我想知道接收和解析此请求的最佳方式是什么?

在我看来 - 也许有人可以说得更多,那就是选择 WebAPI。它使用起来很简单,只是一些代码,所以它很轻。您有很多工具可以在 .NET 中处理 XML 文档,所以这对您来说不会有任何问题。

还有一件事。在你的 XML 中有错误,结束标记 "ReceiveStatusUpdate" 拼写错误。

这在开始时会有帮助:http://www.asp.net/web-api/overview/getting-started-with-aspnet-web-api/tutorial-your-first-web-api 然后你可以使用 Fiddler post 那些 XML 到你的 WebAPI。

实现此目的的最简单方法是使用老式的 asmx Web 服务。

通过 Web 公开 API 需要大量工作,因为它不支持开箱即用的 SOAP 绑定。

您可以使用 WCF 服务,但它们的配置可能很繁琐且耗时,这是为它们的灵活性付出的代价。

简而言之,如果您只需要支持 SOAP 绑定,请使用专为该工作制作的工具 - asmx 网络服务。

只需向您的 Web 服务 (ASMX) 类型的 MVC 项目添加一个新项目,示例如下(您显然需要在单独的文件中定义 StatusUpdate class)。

/// <summary>
/// Summary description for StatusWebService
/// </summary>
[WebService(Namespace = "http://test.com")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
// To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line. 
// [System.Web.Script.Services.ScriptService]
public class StatusWebService : System.Web.Services.WebService
{

    [WebMethod]
    public void ReceiveStatusUpdate(StatusUpdate StatusUpdate)
    {
        //Do whatever needs to be done with the status update
    }
}

public class StatusUpdate
{
    public string Reference { get; set; }
    public string ThirdPartyReference { get; set; }
    public string Status { get; set; }
}

这样做的方式有点老套,但它对我有用,而且它是我需要处理的一次性请求类型。我基本上把请求体拉出来并用 XDocument

解析它
public ActionResult Update()
{
    var inputStream = Request.InputStream;
    inputStream.Seek(0, SeekOrigin.Begin);
    var request = new StreamReader(inputStream).ReadToEnd();
    var soapRequest = XDocument.Parse(request);
    ...
}

可能不是最好的答案,但这是我现在正在做的。

[HttpPost]
public IHttpActionResult HotelAvailRQ(HttpRequestMessage request)
{
    // Parse the SOAP request to get the data payload
    var xmlPayload = MyHelper.GetSoapXmlBody(request);

    // Deserialize the data payload
    var serializer = new XmlSerializer(typeof(OpenTravel.Data.CustomAttributes.OTA_HotelAvailRQ));
    var hotelAvailRQ = (OpenTravel.Data.CustomAttributes.OTA_HotelAvailRQ)serializer.Deserialize(new StringReader(xmlPayload));

    return Ok();
}

帮手class

public static class MyHelper
{
    public static string GetSoapXmlBody(HttpRequestMessage request)
    {
        var xmlDocument = new XmlDocument();
        xmlDocument.Load(request.Content.ReadAsStreamAsync().Result);

        var xmlData = xmlDocument.DocumentElement;
        var xmlBodyElement = xmlData.GetElementsByTagName("SOAP-ENV:Body");

        var xmlBodyNode = xmlBodyElement.Item(0);
        if (xmlBodyNode == null) throw new Exception("Function GetSoapXmlBody: Can't find SOAP-ENV:Body node");

        var xmlPayload = xmlBodyNode.FirstChild;
        if (xmlPayload == null) throw new Exception("Function GetSoapXmlBody: Can't find XML payload");

        return xmlPayload.OuterXml;
    }
}