4

我正在尝试在不创建 WCF 客户端的情况下测试 WCF 服务。我有与此处介绍的类似代码/问题。

我希望完全控制 SOAP 有效负载,因此我希望能够发出我自己的 Web 请求/响应并将我自己的 XML 作为参数替换为任何方法。我还希望返回的 SOAP XML 完全按原样,而不创建响应对象、故障异常对象等。

作为参考,我想完全按照SoapUI在您单击执行按钮并获取响应时所做的事情。我只是假设 SoapUI 不是创建 WCF 客户端、构建请求和调用方法,而是向 WCF 服务发出完整的 SOAP 调用并显示结果。

在回答评论中的问题时,我不想创建 WCF 客户端的原因是我希望与服务的任何和所有更改隔离,不必重建引用、修改我自己的代码、创建单独的每个新服务/方法等的代码,因为这个过程在每次构建后自动启动,没有交互。

所以,我有数十万个测试 XML 参数,我将它们传递给数百个方法,而不关心它们是什么。我们已经在 ASMX Web 服务上做了多年,并且一种方法(与上面的链接非常相​​似)处理了所有 Web 服务/方法/测试参数。

切换到 WCF 后,我会遇到内部服务器错误,尤其是在测试无效的 XML 节点时:缺少必需的节点、重复名称的创建方法中的错误等(任何错误情况)。我认为有一种简单的方法可以以相同的方式使用 WCF 执行此操作是有道理的。

我想要确切的 SoapUI 发回的内容,我只需要知道它是如何做到的。

4

2 回答 2

4

@John Saunders 在他的评论中是正确的。无论您使用 ASMX 做什么,都应该能够使用 WCF。事实上,只要您执行正确的 SOAP 请求,您的 Web 服务使用何种框架/技术并不重要。

WCF只是一个帮助构建面向服务的应用程序的框架。与任何其他此类框架一样,它使您可以专注于您将提供的实际服务,并负责将该服务公开为 SOAP Web 服务所需的所有管道功能。

至于 SoapUI,它是一个 Java 工具,可让您测试 Web 服务。当您向它提供 WSDL 时,它会动态创建请求样本,然后使用(如果我没记错的话)Http Client将这些请求样本发送到 Web 服务。

如果您有 WCF Web 服务,就不会发生什么特别的事情。即使使用这样的基本客户端,它仍然是 SOAP 通信:

public class Program
{
    public static void Main(string[] args)
    {
        // OK, this is not a WCF web service, but that should not matter :D
        string endpoint = "http://www.html2xml.nl/Services/Calculator/Version1/Calculator.asmx";

        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(endpoint);
        request.ContentType = "text/xml"; // or application/soap+xml for SOAP 1.2
        request.Method = "POST";
        request.KeepAlive = false;

        //In case you have a proxy to resolve the server name also add these lines
        var proxyServer = new WebProxy("XX.XX.XX.XX", 1234);
        proxyServer.Credentials = CredentialCache.DefaultCredentials; // or username + password
        request.Proxy = proxyServer;

        // you can read these from files
        string payload = @"<soapenv:Envelope xmlns:soapenv=""http://schemas.xmlsoap.org/soap/envelope/"" xmlns:tem=""http://tempuri.org/"">
                               <soapenv:Header/>
                               <soapenv:Body>
                                  <tem:Add>
                                     <tem:a>1</tem:a>
                                     <tem:b>2</tem:b>
                                  </tem:Add>
                               </soapenv:Body>
                            </soapenv:Envelope>";

        byte[] byteArray = Encoding.UTF8.GetBytes(payload);
        request.ContentLength = byteArray.Length;

        Stream requestStream = request.GetRequestStream();
        requestStream.Write(byteArray, 0, byteArray.Length);
        requestStream.Close();

        HttpWebResponse response = null;
        try
        {
             response = (HttpWebResponse)request.GetResponse();
        }
        catch (WebException ex)
        {
             response = (HttpWebResponse)ex.Response;
        }

        Console.WriteLine(string.Format("HTTP/{0} {1} {2}\n", response.ProtocolVersion, (int)response.StatusCode, response.StatusDescription));

        // you can write this to files
        Stream responseStream = response.GetResponseStream();
        StreamReader reader = new StreamReader(responseStream);
        Console.WriteLine(reader.ReadToEnd());

        // cleanp
        reader.Close();
        requestStream.Close();
        responseStream.Close();
        response.Close();
    }
}

您会收到一个 SOAP 响应,在本例中是这样的:

HTTP/1.1 200 OK

<?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>
        <AddResponse xmlns="http://tempuri.org/">
            <AddResult>3</AddResult>
        </AddResponse>
    </soap:Body>
</soap:Envelope>

并且它是生成它的 ASMX 还是 WCF 或其他任何东西都没有关系。它是对 HTTP 请求的响应。

相反,如果您发送无效消息,例如:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tem="http://tempuri.org/">
   <soapenv:Header/>
   <soapenv:Body>
      <tem:Add>
         <tem:a>x</tem:a>
         <tem:b>y</tem:b>
      </tem:Add>
   </soapenv:Body>
</soapenv:Envelope>

你会得到一个错误,比如:

HTTP/1.1 500 Internal Server Error

<?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>
        <soap:Fault>
            <faultcode>soap:Client</faultcode>
            <faultstring> ... exception stacktrace here ... </faultstring>
            <detail />
        </soap:Fault>
    </soap:Body>
</soap:Envelope>

您可以使用 SoapUI 自动化测试,甚至将它们与Junit集成,您甚至可以使用JMeter之类的东西,尽管它不是专门为 Web 服务(如 SoapUI)设计的,但它可以测试 SOAP。您当然可以使用我添加到答案中的基本客户端。

于 2012-05-19T14:20:02.547 回答
0

除了我之外,这个问题的答案可能对每个人来说都是显而易见的......但它是:我遇到了(500)内部服务器错误并且不知道该怎么做。事实证明,这对每个人来说都是显而易见的,您必须捕获 WebException 错误。WebException 有一个响应,您可以使用它来获取故障条件、完整响应等。我正在捕获一个异常,但不是专门针对 WebException。抱歉,如果我让任何人感到困惑,但我只是在发生错误情况时遇到问题,否则所有代码示例(甚至是我的原始代码示例)都在工作。

我想我可以将此作为另一个问题发布,但这是典型的行为吗?即使对于尝试创建重复记录/项目、无效名称等简单的错误,也会引发 WebException?我确定由于缺乏经验,我希望错误响应以与成功响应相同的方式返回,而不会出现内部服务器错误并且不需要在服务之外捕获 WebException(除非它确实是“网络”例外)。

感谢您的所有回答。

于 2012-05-21T20:01:05.720 回答