我正在尝试在不创建WCF客户端的情况下测试WCF服务。我有类似的代码/问题,如此处所示。
我希望完全控制SOAP负载,因此我希望能够发出自己的Web请求/响应,并将自己的XML作为参数替换到任何方法中。我还希望返回SOAPXML完全一样,而不创建响应对象、故障异常对象等。
作为参考,我想在单击执行按钮并返回响应时做SoapUI正在做的事情。我只是假设SoapUI没有创建WCF客户端、构建请求和调用方法,而是向WCF服务发出完整的SOAP调用并显示结果。
为了回答评论中的问题,我不想创建WCF客户端的原因是,我希望与服务的任何和所有更改隔离开来,不必重建引用、修改我自己的代码、为每个新服务/方法创建单独的代码等,因为这个过程在每次构建后都会自动启动,没有交互。
所以,我有成千上万的测试XML参数,我传递给数百个方法,而不关心它们是什么。我们已经在ASMX Web服务上做了多年,一个方法(与上面的链接非常相似)处理了所有Web服务/方法/测试参数。
随着切换到WCF,我得到了内部服务器错误,尤其是在测试无效的XML节点时:缺少所需的节点,创建方法中的重复名称错误等(任何错误条件)。我认为有一种简单的方法可以用WCF以同样的方式做到这一点是有意义的。
我想要SoapUI到底发回了什么,我只需要知道它是如何做到的。
@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。你可以在课程之外使用我添加到答案中的基本客户端。
这个问题的答案可能对除了我之外的每个人来说都是显而易见的…但事实是:我收到了一个(500)内部服务器错误,不知道该怎么办。事实证明,对每个人来说,这可能也是显而易见的,你必须捕获一个WebException错误。WebException有一个响应,你可以使用它来获取故障条件、完整响应等。我捕获了一个异常,但不是专门针对WebException的。抱歉,如果我让任何人感到困惑,但我只有在发生错误情况时才会遇到问题,否则所有的代码示例(甚至我的原始代码)都在工作。
我想我可以将此作为另一个问题发布,但这是典型的行为吗?即使是像尝试创建重复记录/项目、无效名称等这样简单的错误,也会抛出WebException?我敢肯定,由于缺乏经验,我希望错误响应以与成功响应相同的方式返回,而不会出现内部服务器错误,也不需要在服务外部捕获WebException(除非它确实是“Web”异常)。
谢谢你所有的回答。