Search code examples
silverlight.net-4.0wcf-clientsilverlight-5.0

Consume SOAP Web Service in Silverlight


I'm attempting to consume a SOAP service in a Silverlight 5 application and I'm completely lost. This is my first Silverlight app and only my second time using web services in a .NET application.

In a separate .NET application, the only way I was able to get it to work was by adding the WSDL as a Web Reference; the application would not build when I added it as a Service Reference. In talking to the WSDL provider, I discovered that the WSDL was compiled using the .NET 2.0 framework...hence the need to add it as a Web Reference.

From the research I've done thus far, I see that Silverlight doesn't support adding a Web Reference. So I tried adding it to the hosting ASP.NET application as a Web Reference then started the server.

Back in my Silverlight app, I selected the option to add a Service Reference and pointed to the WSDL file now at http://localhost:55265/Web%20References/THINKWebService/SLWebSvc_734_Upgrade.wsdl. Visual Studio seemed to pick it up just fine and generate the proxies.

Here's where I start to get stuck. If my research is correct, a WCF reference was created and should be used in that manner. I've never used WCF so I did some reading on how to send/receive requests and this is the best code I've come up with, based on examples in the MSDN library (I inserted it into a button click event so I would know exactly when the code was executing):

private void Button1Click(object sender, RoutedEventArgs e)
{
  var client = new ThinkSoapClient();
  var userLoginData = new user_login_data {login = "foo", password = "bar"};
  var customerIdentifier = new customer_identifier {customer_id = 6677070};
  // the debugger halts on this next line and
  // references the "dsn"...it's the 4th argument
  client.CustomerLoginInfoSelectAsync(userLoginData, customerIdentifier, "", "myDSN");
  // I'm not sure if this next line is even needed
  client.CustomerLoginInfoSelectCompleted += CustomerLoginInfoSelectCallback;
  MessageBox.Show(string.Format("CustomerLoginInfoSelectAsync({0},{1})", userLoginData, customerIdentifier));
}

// here's the callback method
static void CustomerLoginInfoSelectCallback(object sender, CustomerLoginInfoSelectCompletedEventArgs e)
{
  MessageBox.Show(string.Format("CustomerLoginInfoSelect Result: {0}", e.Result));
}

As I mentioned in the code above, the debugger halts when executing the client.CustomerLoginInfoSelectAsync method. Here's the error message: XmlSerializer attribute System.Xml.Serialization.XmlAttributeAttribute is not valid in dsn. Only XmlElement, XmlArray, XmlArrayItem and XmlAnyElement attributes are supported when IsWrapped is true.

From the research I've done, I think this error is being caused because the the SOAP action element contains an attribute dsn (not sure, though, if I would be getting this error if the sub-elements also had attributes).

I did a find/replace for IsWrapped=true to IsWrapped=false in Reference.cs but I got the same error but the last word was false instead of true.

I'm not sure if I'm making any sense as to what I'm after, so here's what the generated XML should look like in case it helps:

...
  <customer_login_info_select_request dsn="myDSN">
    <user_login_data>
      <login>foo</login>
      <password>bar</password>
    </user_login_data>
    <customer_identifier>
      <customer_id>6677070</customer_id>
    </customer_identifier>
    <login/> <!--corresponds to the empty string in the call to CustomerLoginInfoSelectAsync-->
  </customer_login_info_select_request>
...

So at this point, I'm completely lost. Any insights would be greatly appreciated. If there's any other info I can provide, please let me know.


Solution

  • While possible the normal solution would be to assume it is "just another data source" and use the Web reference on your Server side instead to provide data (and to provide insulation against future changes).

    Silverlight App <=> Silverlight Web Services <= External/Legacy Web Service
    

    Keep your Silverlight app slim and let the server do any heavy lifting for you.