views:

357

answers:

1

I have a web service that I want to access when it is added as a web reference to my C# project. A particular method in the web service takes a SQL query string and returns the results of the query as a custom type. When I add the web service reference, the method shows up as returning DataSet[] instead of the custom type. This is fine provided I can still somehow access the data returned from the query within those DataSet objects. I ran a particular query that should return 6 rows; I got back a DataSet[] array with 6 elements. However, when I iterate over those DataSet objects, none of them has any tables (via the Tables property on the DataSet). What gives? Where is my data?

The web service is tested and works when I use it as a data source in a Report Builder 2.0 report. I am able to send an XML SOAP query to the web service and get back XML results containing my data.

Here's a sample of how I'm getting the DataSet[] array:

var service = new MyWebService
    {
        Credentials = System.Net.CredentialCache.DefaultCredentials
    };
DataSet[] dataSets = service.MethodThatReturnsQueryResults(queryString);

// The body of this loop is skipped:
foreach (DataSet ds in dataSets.Where(ds => ds.Tables.Count > 0))
{
    // extract data from DataSet ds
}

Edit: here is what the method looks like in the auto-generated Reference.cs that got created when I added the web reference:

[return: System.Xml.Serialization.XmlArrayItemAttribute("SomeCustomType")]
public System.Data.DataSet[] MethodThatReturnsQueryResults(
    string selectSQLQuery) {
        object[] results = this.Invoke("MethodThatReturnsQueryResults", 
            new object[] { selectSQLQuery});
    return ((System.Data.DataSet[])(results[0]));
}

So it's definitely returning a System.Data.DataSet[], but I wonder if something is happening such that the custom type used in the web service, SomeCustomType, is not getting translated correctly in that auto-generated method, hence the empty DataSet objects. I'm hesitant to edit this auto-generated method. I have access to the web service code; should I do something to it to ensure SomeCustomType can be cast to DataSet[]?

Edit: I feel like I could do better if I just got back the raw XML SOAP response from the web service. How can I do this instead of getting the "translated" version that comes back as DataSet[]?

+1  A: 

I ended up removing the web service reference from my project and instead wrote a utility class for sending a SOAP request and getting the response back in XML, thanks to this tutorial. Here are a couple snippets:

public XmlDocument SendSoapRequest(XmlDocument soapRequest)
{
    var webRequest = getWebRequest();
    Stream requestStream = webRequest.GetRequestStream();
    soapRequest.Save(requestStream);
    requestStream.Close();
    WebResponse webResponse = webRequest.GetResponse();
    requestStream = webResponse.GetResponseStream();
    var soapResponse = new XmlDocument();
    soapResponse.Load(new XmlTextReader(new StringReader(
        new StreamReader(requestStream).ReadToEnd()
    )));
    return soapResponse;
}

private HttpWebRequest getWebRequest()
{
    var webRequest = (HttpWebRequest)WebRequest.Create(Url);
    webRequest.Credentials = CredentialCache.DefaultCredentials;
    webRequest.Headers.Add("SOAPAction", SoapAction);
    webRequest.ContentType = ContentType;
    webRequest.Accept = AcceptHeader;
    webRequest.Method = RequestMethod;
    return webRequest;
}

I then use an XPath query to navigate the returned XmlDocument and get the data I want, the data that was not showing up in the DataSet[] that I got back from the web service when I used a web reference. I already had a class that implements IXmlSerializable so once I navigate the returned XML with XPath, I just pass an XmlReader to my class's ReadXml method and the class instance gets populated.

Sarah Vessels