views:

432

answers:

1

Part of my current work involves using an external web service, for which I have generated client proxy code (using the WSDL.exe tool).

I need to test that the web service correctly handles the absence of mandatory fields. For instance, Surname and Forename are mandatory - if they are absent from the call, then a SOAP fault block should be returned.

As you may have guessed, I cannot exclude any mandatory fields from my web service call when using the auto-generated proxy code because of compile-time checking against the schema.

What I have done instead is to use HttpWebRequest and HttpWebResponse to send/receive a manually-formatted SOAP envelope to the web service. This works, but because the service returns a 500 HTTP status code, an exception is raised on the client and the response (containing that SOAP fault block I need) is null. Basically I need the return stream to get at the error data so I can complete my unit test. I know the correct data is being returned because I can see it on my Fiddler trace, but I just can't get at it in my code.

Here's what I'm doing for the manual call, with the names changed to protect the innocent:

private INVALID_POST = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
    "<soap:Envelope ...rest of SOAP envelope contents...";

private void DoInvalidRequestTest()
{
    HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create("https://myserviceurl.svc");
    request.Method = "POST";
    request.Headers.Add("SOAPAction",
        "\"https://myserviceurl.svc/CreateTestThing\"");
    request.ContentType = "text/xml; charset=utf-8";
    request.ContentLength = INVALID_POST.Length;
    request.KeepAlive = true;

    using (StreamWriter writer = new StreamWriter(request.GetRequestStream()))
    {
        writer.Write(invalidPost);
    }

    try
    {
        // The following line will raise an exception because of the 500 code returned
        HttpWebResponse response = (HttpWebResponse)request.GetResponse();
        if (response.StatusCode == HttpStatusCode.OK)
        {
            using (StreamReader reader = new StreamReader(response.GetResponseStream()))
            {
                string reply = reader.ReadToEnd();
            }
        }
    }
    catch (Exception ex)
    {
        ... My exception handling code ...
    }
}

Please note that I am not using WCF, just WSE 3.

+1  A: 

What about write your own SoapHttpClientProtocol and using SoapExtensions?

    [WebServiceBinding()]
 public class WebService
 : System.Web.Services.Protocols.SoapHttpClientProtocol
 {
  [SoapTrace]
  public object[] MethodTest(string param1, string param2)
  {
   object[] result = this.Invoke("MethodTest", new object[] { param1, param2 });
   return (object[])result[0];
  }
 }
Jan Remunda
Thank you very much for your answer, Ishtar. Unfortunately this does not work for me - behind the scenes, Invoke() attempts to serialize the object parameters into the matching strong types that have been generated by the wsdl.exe tool.If I miss a parameter out, set it to an empty string, or set it to null, I get an XmlSerializer exception and the web service is not called :(
Dave R.