Post HTML 中的 SOAP 请求并获得响应

Post a SOAP request in HTML and get response

我正在使用 WCFStorm 来调试一个非常简单的 SOAP 端点:

http://www.dneonline.com/calculator.asmx?WSDL

此类端点可用于请求 4 种基本算术计算并检索响应:在示例中,我请求数字 35,我收到响应8,一切顺利!

我现在想创建一个 HTML 页面,它可以在不使用 WCFStorm 的情况下执行相同的操作。这是我的代码:

<html>

<head>
    <title>Calling Web Service from jQuery</title>
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.3/jquery.min.js"></script>
    <script type="text/javascript">
        $(document).ready(function() {
            $("#btnCallWebService").click(function(event) {
                var wsUrl = "http://www.dneonline.com/calculator.asmx?WSDL";
                var soapRequest = '<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">   <soap:Body> <getQuote xmlns:impl="http://www.dneonline.com/calculator.asmx?WSDL">  <intA>' + $("#intA").val() + '</intA> <intB>' + $("#intB").val() + '</intB>  </getQuote> </soap:Body></soap:Envelope>';
                alert(soapRequest)
                $.ajax({
                    type: "POST",
                    url: wsUrl,
                    contentType: "text/xml",
                    dataType: "xml",
                    data: soapRequest,
                    success: processSuccess,
                    error: processError
                });

            });
        });

        function processSuccess(data, status, req) {
            alert('success');
            if (status == "success")
                $("#response").text($(req.responseXML).find("Int32").text());

            alert(req.responseXML);
        }

        function processError(data, status, req) {
            alert('err' + data.state);
            //alert(req.responseText + " " + status);
        }
    </script>
</head>

<body>
    <h3>
        Calling Web Services with jQuery/AJAX
    </h3>
    Enter the numbers:
    <input id="intA" type="string" />
    <input id="intB" type="string" />
    <input id="btnCallWebService" value="Call web service" type="button" />
    <div id="response"></div>
</body>

</html>

但不幸的是我只能收到:errundefined。 我哪里错了?

Where am I wrong?

  1. 请求 payload/data 格式不正确:

    对于 SOAP 1.1:(请求和响应格式在 XML 中)

    <?xml version="1.0" encoding="utf-8"?>
    <soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
      <soap:Body>
        <Add xmlns="http://tempuri.org/">
          <intA>int</intA>
          <intB>int</intB>
        </Add>
      </soap:Body>
    </soap:Envelope>
    

    对于 SOAP 1.2:(请求和响应格式采用 SOAP + XML)

    <?xml version="1.0" encoding="utf-8"?>
    <soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
      <soap12:Body>
        <Add xmlns="http://tempuri.org/">
          <intA>int</intA>
          <intB>int</intB>
        </Add>
      </soap12:Body>
    </soap12:Envelope>
    

    有关详细信息,请参阅计算器 Web 服务 docs

  2. 正如我原来的回答所指出的,这是一个需要考虑的非常重要的事情:计算器 Web 服务端点(http://www.dneonline.com/calculator.asmx?WSDL) does not have the proper CORS header (Access-Control-Allow-Origin) which is required when making CORS requests — excerpt from MDN's article 关于 跨源资源共享(CORS):

    A web application executes a cross-origin HTTP request when it requests a resource that has a different origin (domain, protocol, or port) than its own origin.

    An example of a cross-origin request: The frontend JavaScript code for a web application served from http://domain-a.com uses XMLHttpRequest to make a request for http://api.domain-b.com/data.json.

    For security reasons, browsers restrict cross-origin HTTP requests initiated from within scripts. For example, XMLHttpRequest and the Fetch API follow the same-origin policy. This means that a web application using those APIs can only request HTTP resources from the same origin the application was loaded from, unless the response from the other origin includes the right CORS headers.

因此,如果上述(第二段)适用于您,即您实际上并不是从同一个 origin/domain 发出 CORS/AJAX 请求, 那么你可以:

  1. 如果您拥有计算器网络服务 (dneonline.com) 的 domain/website.. 或对其管理有控制权,则可以在该站点上 enable CORS

  2. 或者如果您的网站有服务器端应用程序,如 PHP 或 Python,那么您可以使用服务器端脚本来发出请求 — example in PHP,你可以让 calculator.php 向 API 发出远程请求,然后你的脚本使 AJAX请求到calculator.php.

  3. 或者您可以使用 CORS 代理 ,例如我试过的 https://cors-anywhere.herokuapp.com — 查看下面的演示。

演示:使用 https://cors-anywhere.herokuapp.com

向未启用 CORS 的资源发出 AJAX 请求

$('#btnCallWebService').click(function(event) {
  $('#intA').val(Number($('#intA').val() || 0).toFixed(0) || 0);
  $('#intB').val(Number($('#intB').val() || 0).toFixed(0) || 0);
  if ('0' === $('#intA').val() && '0' === $('#intB').val()) {
    alert('Non-zeros only.. for this demo.');
    return;
  }

  var $btn = $(this), _btn_text = $btn.val();
  $btn.prop('disabled', true).val('Calculating..');
  $('#response').hide();

  var wsUrl = 'http://www.dneonline.com/calculator.asmx';
  var soap12Request = '<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">  <soap12:Body>    <Add xmlns="http://tempuri.org/">      <intA>' + $('#intA').val() + '</intA>      <intB>' + $('#intB').val() + '</intB>    </Add>  </soap12:Body></soap12:Envelope>';

  $.ajax({
    type: 'POST',
    url: 'https://cors-anywhere.herokuapp.com/' + wsUrl,
    contentType: 'application/soap+xml', // can also be text/xml
    dataType: 'xml',
    data: soap12Request,
    success: function(xml){
      var $doc = $(xml);
      $('#answer').html($doc.find('AddResult').text());
      $('#response').show();
    },
    complete: function(){
      $btn.val(_btn_text).prop('disabled', false);
    }
  });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

Enter the numbers:
<input id="intA" type="number" placeholder="No decimals" /> <code>+</code>
<input id="intB" type="number" placeholder="No decimals" />
<input id="btnCallWebService" value="Call web service (SOAP 1.2)" type="button" />
<div id="response" style="display:none">
  The answer is: <b id="answer"></b>
</div>

由于 同源策略 ,无法在 http://www.example.com and make ajax call to http://www.anotherdomain.com 上创建页面。

解决方案?

  • 在 WCF 服务上启用 CORS
  • 或者,创建一个后端代理来使用 WCF,然后ajax调用这个

如果您无法将 javascript 移动到与 Web 服务相同的域中,唯一可靠的方法是构建一个服务器端脚本,该脚本将与您的 javascript代码。因此,您将向您的服务器端脚本发送一个 AJAX 请求,该脚本将调用远程 Web 服务并 return 结果。以下链接显示了如何创建一个简单的服务器端 ASP.Net MVC 来使用 WCF 服务:

jQuery SOAP 提供了一个 jQuery 插件,用于使用 SOAP 与 Web 服务进行通信,假设您的 javascript 和 Web 服务在同一域中。

Sally CJ 对此做出了很好的回复post,我相信当之无愧。 我学到了很多关于 CORS 的东西。

不过我不得不提一下,有一种方法可以使用简单的 HTML 文件来存档结果: