WCF–Testing the DataService
The quickest way to test that the Data Service is working is to create a simple Windows Forms based application as this will be able to connect without encountering any of the cross domain issues that a Silverlight application will hit.
Once this test has completed then the WCF service will be changed so that a Silverlight application can be created.
Create a new Windows Forms based application in VS2010. Its best to develop the application in a separate instance of VS2010 rather than adding new project to the solution because then the DataService can be left running while the client is being developed.
Ensure that the ConsoleApplicationWCF is running and the DataService console window is displayed.
Add a button and a label to the Form1 that will have been created automatically by VS.
In the Project Solution right click on References and select Add Service Reference. Enter the address of the DataService (e.g. http://localhost:1234/DataService). Click the Advanced button and tick the ‘Generate asynchronous operations’ checkbox. Asynchronous operations are slightly more tricky to use but is the only option when using Silverlight so it may as well be implemented now.
Once the service reference has been created (and you can see that the process creates quite a bit of code and support files if you ‘show all files’ in the project Solution explorer) it can be used with relative ease.
One of the really great things about WCF is how much work the Microsoft developers have put into hiding the complexity of what is a very complex process.
The code pretty much writes itself, you only have to remember a couple of names in order to get it working.
The starting point when using the service reference is to create a reference to the service code that has been used, the will be called DataServiceClient.
DataServiceClient dataService = null;
Adding this will report an error. Right clicking on DataServiceClient and selecting Resolve will add the correct using statement to the class (it should be “using WindowsFormsWCF.DataService”).
Using the event driven asynchronous access pattern that is exposed via the code that has been generated during the creation of the service reference exposes the functionality of WCF. VS2010 IntelliSense will virtually fill out the code to access the service. So the button click code should look like this:
private void button1_Click(object sender, EventArgs e) { dataService.GetDateTimeCompleted += new EventHandler
<GetDateTimeCompletedEventArgs>(dataService_GetDateTimeCompleted); dataService.GetDateTimeAsync(); }
The GetDateTimeCompleted delegate simply needs an appropriate event handler to be added and IntelliSense will event generate the name of the handler “dataService_GetDateTimeCompleted” all that needs to be done is add it to the code.
void dataService_GetDateTimeCompleted(object sender, DataService.GetDateTimeCompletedEventArgs e) { try { XElement xResult = (XElement)e.Result; string date = xResult.Element("Date").Value; string time = xResult.Element("Time").Value; label1.Text = string.Format("The date is: {0}\nThe time is: {1}", date, time); } catch (Exception ex) { label1.Text = string.Format("Error occurred: {0}", ex.Message); } }
The only bit of work that has be hand cranked is to remember that the event handler will have the following parameters:
(object sender, DataService.GetDateTimeCompletedEventArgs e)
The e.Result will be returning an XElement, as this was defined in the original service. I’m simply grabbing the Date and Time elements from the XML, formatting them and showing the result in the label.
The code for the application is:
using System; using System.Windows.Forms; using WindowsFormsWCF.DataService; using System.Xml.Linq; namespace WindowsFormsWCF { public partial class Form1 : Form { DataServiceClient dataService = null; public Form1() { InitializeComponent(); dataService = new DataServiceClient(); } private void button1_Click(object sender, EventArgs e) { dataService.GetDateTimeCompleted += new EventHandler<GetDateTimeCompletedEventArgs>(dataService_GetDateTimeCompleted); dataService.GetDateTimeAsync(); } void dataService_GetDateTimeCompleted(object sender, DataService.GetDateTimeCompletedEventArgs e) { try { XElement xResult = (XElement)e.Result; string date = xResult.Element("Date").Value; string time = xResult.Element("Time").Value; label1.Text = string.Format("The date is: {0}\nThe time is: {1}", date, time); } catch (Exception ex) { label1.Text = string.Format("Error occurred: {0}", ex.Message); } } } }
Transforming this code to Silverlight is pretty simple. Create a new Silverlight Application project in VS2010 (remove the checkmark for hosting in a new web site).
In the MainPage.xaml add a Button and a TextBox. Create the Service Reference and then paste in the following code:
using System; using System.Windows; using System.Windows.Controls; using SilverlightApplicationWCF.DataService; using System.Xml.Linq; namespace SilverlightApplicationWCF { public partial class MainPage : UserControl { DataServiceClient dataService = null; public MainPage() { InitializeComponent(); dataService = new DataServiceClient(); } private void button1_Click(object sender, RoutedEventArgs e) { try { dataService.GetDateTimeCompleted += new EventHandler<GetDateTimeCompletedEventArgs>(dataService_GetDateTimeCompleted); dataService.GetDateTimeAsync(); } catch (Exception ex) { textBlock1.Text = string.Format("Error occurred: {0}", ex.Message); } } void dataService_GetDateTimeCompleted(object sender, DataService.GetDateTimeCompletedEventArgs e) { try { XElement xResult = (XElement)e.Result; string date = xResult.Element("Date").Value; string time = xResult.Element("Time").Value; textBlock1.Text = string.Format("The date is: {0}\nThe time is: {1}", date, time); } catch (Exception ex) { textBlock1.Text = string.Format("Error occurred: {0}", ex.Message); } } } }
Apart from a few name differences its the same code!
Run the application and you will get a warning about debugging issues when using web services (you can see what’s coming soon…). Ignore the warning and continue to run the application and while the Silverlight form will display, as soon as you click the button an cross-domain error will be thrown:
The next post will show how this is solved quite elegantly.
Leave a Reply