2012-05-15 166 views
3

我想在不创建WCF客户端的情况下测试WCF服务。我有类似的代码/问题here使用SOAP调用WCF服务

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

作为参考点,我想要完成SoapUI在单击执行按钮时所做的操作,并且得到回应。我只假设SoapUI不创建WCF客户端,构建请求并调用方法,而是向WCF服务发出完整的SOAP调用并显示结果。

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

因此,我拥有成千上万的测试XML参数,我传入了数百种方法,而不关心它们是什么。我们在ASMX网络服务上做了多年,其中一种方法(非常类似于上述链接)处理所有Web服务/方法/测试参数。

随着切换到WCF我尤其是在测试无效的XML节点时出现内部服务器错误:缺少所需节点,重复名称的创建方法中的错误等(任何错误条件)。我认为这是有道理的,有一个简单的方法来做到这一点与WCF以相同的方式。

我想要的是SoapUI发回的东西,我只需要知道它是如何做到的。

+0

我不确定你的意思。就像您所说的那样,通过使用POST Web请求发送SOAP XML来进行调用。 WCF将处理事物的序列化和Web请求/响应级别。 – lockstock

+0

@s mac:我建议你解释你正在尝试做什么,而不是你目前如何尝试。删除所有的评论,而是建立一个简单,简洁的问题。你提到你是一个测试人员。你想测试一个WCF Web服务并且想要完全控制SOAP有效载荷。是吗?为什么你想在低级别而不是使用WCF客户端或SoapUI? – JohnDoDo

+0

好的,约翰......我再次尝试。由于我不熟悉WCF或SOAP,这是我知道如何解释它的唯一方法。我相信有一个明显的方法可以做到(对你和其他人),我只是不知道它是什么,我已经寻找好几天了。如果您有更多问题,请告诉我。谢谢。 –

回答

3

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

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

至于SoapUI,它是一个Java工具,允许您测试Web服务。当你为它提供一个WSDL时,it dynamically creates请求样本然后发送到Web服务(如果我没有弄错的话)Http Client

如果您有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> 

可以automate the tests with SoapUI甚至与Junit整合它们,你可以甚至使用类似JMeter的东西,虽然不是专门为Web服务设计的(如SoapUI)it can test SOAP。你可以在课程中使用我添加到我的答案中的基本客户端。

+0

感谢您的回复,我同意。它应该以同样的方式工作。但是,事实并非如此。即使使用您的代码,我也会得到相同的结果。如果我有一个“成功”的例子,它可以正常工作。但是,如果我得到任何类型的错误条件(无效数据,无效条件,无法执行任何原因的操作等),我得到一个(500) - 内部服务器错误。我已经尝试过所有我见过的例子。由于SoapUI能够在响应中对调用进行copmlete并返回错误,因此我假设错误在我的某处。但是,谢谢。尽管它没有为我解决,但它有助于我的理解。 –

+0

@s mac:我在我的答案中增加了一些细节(主要是'Console.WriteLine(string.Format(“HTTP/{0} {1} {2} \ n”...')之前的行。如果您现在能够从500 HTTP响应中获取SOAP错误。 – Bogdan

+0

这正是我的问题。我正在输入你想发布的答案。但是,是的,谢谢。我只是不知道处理WebException。 –

0

这个问题的答案很可能对每个人都是显而易见的......但是这里是:我得到一个(500)内部服务器错误,不知道该如何处理它。事实证明,对所有人来说可能是很明显的,你必须捕捉到一个WebException错误。 WebException有一个响应,您可以用来获取错误条件,完整响应等。我正在捕获一个异常,但不是专门针对WebException。对不起,如果我把任何人都弄糊涂了,但是在发生错误时我只会遇到问题,否则所有代码示例(甚至是我的原始代码)都在工作。

我想我可以张贴这是另一个问题,但这是典型的行为?即使对于像尝试创建重复记录/项目,名称无效等错误一样简单,WebException也会被抛出?我相信由于缺乏经验,我期待错误响应以与没有内部服务器错误的成功响应相同的方式返回,并且不需要在服务之外捕获WebException(除非它确实是一个“网络”例外)。

感谢您的答案。

+1

无论何时Web请求无法成功执行,您都会收到异常。有时必须处理一个异常可能是一个麻烦,但替代方案并没有更好的办法,那就是在每次请求后测试状态代码200。您的代码通常有两个执行路径:成功和失败。错误处理程序通常是处理“失败”路径的更简洁的方法 – Bogdan