Using AgFx with Add Service Reference Proxies

Consuming many web services is made much easier with Visual Studio's Add Service Reference dialog. Typically you just point the dialog at a web service that surfaces WSDL, and it generates the proxy objects and interfaces for talking to the service. This is great because it typically saves you a bunch of time parsing XML or SOAP. But it also abstracts out the network access part into a config file, etc.

For this to be useful to AgFx, you need to separate out the request form the result, so here is the pattern that usually works. It can be a bit of a challenge to fill out how to do the request, but it's generally of the following example.

Example - WebServiceX Weather

At WebServiceX, there is a weather service.

If you click that link you'll see the HTTP GET format is as follows:

 

GET /WeatherForecast.asmx/GetWeatherByZipCode?ZipCode=string HTTP/1.1
Host: www.webservicex.net

 

which means to get the weather for 98052 I'd call:

 

http://webservicex.net/WeatherForecast.asmx/GetWeatherByZipCode?ZipCode=98052

 

So we'd just pass that string to our WebLoadRequest in the [IDataLoader].GetLoadRequest implementation.  Easy.

Now, in Deserialize, we do the other half of the operation.  The proxy has generated types that work with XML serialization and that's exactly what the generated client would do when it got the result off the wire, so we can use the generated classes with the XmlSerializer to do the work for us.

In this case the XML looks like this:

 

<?xml version="1.0" encoding="utf-8"?>
<WeatherForecasts xmlns="http://www.webservicex.net">
  <Latitude>float</Latitude>
  <Longitude>float</Longitude>
  <AllocationFactor>float</AllocationFactor>
  <FipsCode>string</FipsCode>
  <PlaceName>string</PlaceName>
  <StateCode>string</StateCode>
  <Status>string</Status>
  <Details>
    <WeatherData>
      <Day>string</Day>
      <WeatherImage>string</WeatherImage>
      <MaxTemperatureF>string</MaxTemperatureF>
      <MinTemperatureF>string</MinTemperatureF>
      <MaxTemperatureC>string</MaxTemperatureC>
      <MinTemperatureC>string</MinTemperatureC>
    </WeatherData>
    <WeatherData>
      <Day>string</Day>
      <WeatherImage>string</WeatherImage>
      <MaxTemperatureF>string</MaxTemperatureF>
      <MinTemperatureF>string</MinTemperatureF>
      <MaxTemperatureC>string</MaxTemperatureC>
      <MinTemperatureC>string</MinTemperatureC>
    </WeatherData>
  </Details>
</WeatherForecasts>

 

And then this is the code that we could write in Deserialize to process it:

 

  public object Deserialize(LoadContext loadContext, Type objectType, Stream stream) {

                // one of the tricks here is to pull the default namespace off of the root type.
                //
                XmlTypeAttribute attr = (XmlTypeAttribute)typeof(WeatherForecasts).
                            GetCustomAttributes(typeof(XmlTypeAttribute), false).FirstOrDefault();

                // now just create the serializer and pass in the data.
                //
                var dcs = new XmlSerializer(typeof(WeatherForecasts), attr.Namespace);


                WeatherForecasts forecasts = (WeatherForecasts) dcs.Deserialize(stream);

                var vm = MyForecastVm();
                vm.LoadContext = loadContext;
                vm.AddForecasts(forecasts);
                return vm;
            }

 

WCF and other service types

Sometimes it takes a bit of work to get this right but the basic steps are:

  1. Use th Add Service Reference Dialog to create the proxy.
  2. Make some calls, and figure out what the request format looks like.  [url:Fiddler|http://www.fiddler2.com/fiddler2] can sometimes help you here when there isn't a doc page available.  WCF generally uses POST requests, so you may need to build POSTs.  See WebLoadRequest which supports this.  (WARNING: POST requests are not super well tested at this point, let me know if you have problems).
  3. Figure out what the deserialiation format is for the objects - usually it's DataContractSerializer, sometimes it's XmlSerializer

Last edited Mar 31, 2011 at 12:35 AM by shawnburke, version 4

Comments

No comments yet.