[Updated for Win8/Dev11 Beta]

Hi all,
With Windows 8 metro styled applications getting a great buzz - I thought this was a perfect time to introduce the WCF support for Metro applications.

We provide support for WCF client inside a Metro application with a subset of features compared to classic desktop applications. See here - http://blogs.msdn.com/b/piyushjo/archive/2011/10/19/wcf-for-metro-apps-supported-functionality.aspx for the supported feature list. This enables you to consume all those awesome web services out there, in your metro app very easily and as we will see – very similar to what you are already used to.

We will start with a simple Metro application in C# and consume an ASMX web service (one of the first weather services I found in my search results). The application in its current form will be a simple weather reporting client taking in a US zip code and displaying the weather by calling an external web service hosted here - http://wsf.cdyne.com/WeatherWS/Weather.asmx.  The point of the demo is to clarify the client experience for Win8 Metro app.
In future blog posts, we will extend the application to include more of supported WCF features and will consume WCF services which is likely going to be the norm.

image

1. Open Visual Studio 11 and create a new Windows Metro style Blank application.

image

2. In your application - right click on References and add the service reference to http://wsf.cdyne.com/WeatherWS/Weather.asmx service just as you do for classic desktop apps. This will generate a service reference to this weather service.

image

3. So far nothing out of the ordinary - everything is exactly the same as what we are used to while adding a service reference to a web service.

The fun starts now:
a) First note that there is no configuration file generated. Metro apps do not support the traditional xml styled application so we have modified our Add Service Reference (ASR) experience from within a metro app to generate code based configuration.
Where will you find this generated code? Go to the Reference.cs file generated under the service reference folder. You will have to click "Show All Files" in Solution explorer.
You will see code like the following for the generated binding and endpoint address:

    
Code Snippet
  1. private static System.ServiceModel.Channels.Binding GetBindingForEndpoint(EndpointConfiguration endpointConfiguration) {
  2.     if ((endpointConfiguration == EndpointConfiguration.WeatherSoap)) {
  3.         System.ServiceModel.BasicHttpBinding result = new System.ServiceModel.BasicHttpBinding();
  4.         result.MaxBufferSize = int.MaxValue;
  5.         result.ReaderQuotas = System.Xml.XmlDictionaryReaderQuotas.Max;
  6.         result.MaxReceivedMessageSize = int.MaxValue;
  7.         result.AllowCookies = true;
  8.         return result;
  9.     }
  10.     throw new System.InvalidOperationException(string.Format("Could not find endpoint with name \'{0}\'.", endpointConfiguration));
  11. }
  12. private static System.ServiceModel.EndpointAddress GetEndpointAddress(EndpointConfiguration endpointConfiguration) {
  13.     if ((endpointConfiguration == EndpointConfiguration.WeatherSoap)) {
  14.         return new System.ServiceModel.EndpointAddress("http://wsf.cdyne.com/WeatherWS/Weather.asmx");
  15.     }
  16.     throw new System.InvalidOperationException(string.Format("Could not find endpoint with name \'{0}\'.", endpointConfiguration));
  17. }

Now this also means that if you need to change any binding properties on the client side - you need to do this in code. You can use the newly generated partial method ‘ConfigureEndpoint’ to implement any changes outside the generated proxy class so that you can update the generated proxy (including Reference.cs) without any fear of your changes being overwritten.

Code Snippet
  1. public partial class WeatherSoapClient : System.ServiceModel.ClientBase<MetroTestApp.WeatherService.WeatherSoap>, MetroTestApp.WeatherService.WeatherSoap {
  2.         
  3.         /// <summary>
  4.         /// Implement this partial method to configure the service endpoint.
  5.         /// </summary>
  6.         /// <param name="serviceEndpoint">The endpoint to configure</param>
  7.         /// <param name="clientCredentials">The client credentials</param>
  8.         static partial void ConfigureEndpoint(System.ServiceModel.Description.ServiceEndpoint serviceEndpoint, System.ServiceModel.Description.ClientCredentials clientCredentials);

b) Next - you will also notice a difference in the style of operations generated for the service.
Note that you only have task based async patterned methods generated. This ensures that there are no blocking calls from the metro styled UI apps, even unknowingly.
If you will generate a similar service reference from a classic desktop app in Dev11 - you will see both synchronous and task based async methods. Task based async pattern is the recommended pattern for doing async programming going forward therefore in Add Service Reference - Advanced dialog, we select it for you by default:

image

 

4) That’s it. Thereafter you can call the service asyn using the following Task based async model:

Code Snippet
  1. private async void GoButton_Click(object sender, RoutedEventArgs e)
  2. {
  3.     WeatherSoapClient proxy = new WeatherSoapClient();
  4.     WeatherReturn result = await proxy.GetCityWeatherByZIPAsync(inputZipCode.Text);
  5.     if (result.Success)
  6.     {
  7.         resultCityState.Text = String.Format("{0}, {1}", result.City, result.State);
  8.         resultDetails.Text = String.Format
  9.             ("\nConditions - {0} \nTemperature - {1}F \nRelative Humidity - {2} \nWind - {3} \nPressure - {4}",
  10.             result.Description, result.Temperature, result.RelativeHumidity, result.Wind, result.Pressure);
  11.     }
  12.     else
  13.     {
  14.         resultCityState.Text = "City not found";
  15.     }
  16. }
 
Note that the method is marked async and we are making the service call with the await keyword.
5) You don’t have to provide any additional capability and the default capability Internet (Client) is sufficient.
image
So that was pretty much it! For you - while developing metro apps - you just need to be aware that:

1) You need to make all configuration in code.
2) You need to make all service calls async using the task based pattern.

Attached is a sample app which contains two projects - one is a metro styled app and another a regular console app making the same service call. You can compare the generated service references to get more insight.


Sample code attached. 

Thanks!