Wahlin on .NET

Simplify Calling a WCF Service from Silverlight

Large-scale Silverlight applications can end up making hundreds of calls from the application to WCF service operations. When I first started building Silverlight applications, I called WCF services using the standard technique, which is to define a client-side class that's used to call the WCF service using the generated service proxy. The service agent class handles instantiating the WCF proxy object and calling the appropriate operations. Listing 1 shows a few examples. Each of the methods accepts the parameters passed to the WCF service as well as a callback method that's called when the service returns data.
public void GetJobs(EventHandler callback)
{
    IJobPlanService proxy = GetProxy();
    proxy.GetJobsCompleted += callback;
    proxy.GetJobsAsync();
}

public void GetEmployees(EventHandler 
  callback)
{
    IJobPlanService proxy = GetProxy();
    proxy.GetEmployeesCompleted += callback;
    proxy.GetEmployeesAsync();
}

public void GetEmployeesByJobID(int jobID, 
  EventHandler callback)
{
    IJobPlanService proxy = GetProxy();
    proxy.GetEmployeesByJobIDCompleted += callback;
    proxy.GetEmployeesByJobIDAsync(jobID);
}

public void GetTimeSheetViews(int? jobID, int? empID, string weekEnding, 
  EventHandler callback)
{
    IJobPlanService proxy = GetProxy();
    proxy.GetTimeSheetViewsCompleted += callback;
    proxy.GetTimeSheetViewsAsync(jobID, empID, weekEnding);
}
Listing 1. Calling WCF service operations using a client proxy object.

After writing nearly the same code method after method (aside from changes in the event name and method name), I opted for a simplified approach that provides a way to make WCF service operation calls using a single method. That way I don't have to continually write wrapper methods just to call a service operation, which can get tedious. Some people will like the following code since it can eliminate a ton of code from your Silverlight project (the code would work fine outside of Silverlight too, by the way). Others won't like it since reflection is involved. I personally don't find that reflection is a problem in this scenario, since it's running on the client-side.

Here's how it works:

1. The CallService method shown in Listing 2 accepts an async callback delegate as well as the parameter data that should be passed to the service. In other words, tell it what method to call once the service returns data as well as what data to pass up to the service operation.

2. When calling the CallService method you must supply the type of EventArgs that will be returned from the service call. This is done using generics.

/// 
/// Used to call a WCF service operation.
/// 
/// The type of EventArgs that will be returned 
/// by the service operation.
/// The method to call once the WCF call 
/// returns (the callback).
/// Any parameters that the service 
/// operation expects.

public void CallService(EventHandler callback, 
  params object[] parameters) where T : EventArgs
{
    string action = typeof(T).Name.Replace("CompletedEventArgs", 
      String.Empty);
    IJobPlanService proxy = new JobPlanServiceClient();
    Type t = typeof(JobPlanServiceClient);
    t.GetEvent(action + "Completed").AddEventHandler(proxy, callback);
    t.InvokeMember(action + "Async", BindingFlags.InvokeMethod, null, 
    proxy, parameters);
}
Listing 2. Creating a re-useable method capable of calling any WCF service operation.

An example of using the CallService method is shown next:

ServiceAgent _Proxy = new ServiceAgent();

public void GetAreasByJobID()
{
    _Proxy.CallService((s,e) => 
      this.CurrentTimeSheetView.Areas = e.Result,
      this.TimeSheetJob.JobID);
}
The GetAreasByJobID method passes a type of GetAreasByJobIDCompletedEventArgs as the generic type to CallService, defines the async callback using a lambda expression (although a separate method could certainly be defined) and passes the parameter that the service operation expects. Multiple parameters can be passed when needed. CallService knows which WCF service operation to call based upon the generic type that's passed, since WCF service proxy object's always create EventArgs classes that end with "CompletedEventArgs".

The CallService‹T› method simply removes the string "CompletedEventArgs" to get the operation name, instantiates the service proxy object and then uses reflection to wire up the appropriate event and async method to call. If you use several different service proxy objects you could certainly handle that as well with generics. I played around with ChannelFactory as well but opted for this approach mainly because it was more straightforward in my opinion, and because I wanted to use the generated WCF proxy anyway.

If scalability was an issue (which is not the case here since this runs on the client-side), then I'd go with the standard approach of using the WCF proxy methods that are generated as shown in the first section of code above. For an application my company is currently working on, this approach to calling WCF service operation has eliminated hundreds of lines of redundant code (which will grow to thousands of lines of eliminated code based on the scope of the project). That means we have less to worry about. The other major benefit is this approach eliminates the time it would have taken to write the wrapper methods.

About the Author

Dan Wahlin (Microsoft MVP for ASP.NET and XML Web Services) is the founder of The Wahlin Group which specializes in .NET and SharePoint onsite, online and video training and consulting solutions. Dan also founded the XML for ASP.NET Developers Web site, which focuses on using ASP.NET, XML, AJAX, Silverlight and Web Services in Microsoft's .NET platform. He's also on the INETA Speaker's Bureau and speaks at conferences and user groups around the world. Dan has written several books on .NET including "Professional Silverlight 2 for ASP.NET Developers," "Professional ASP.NET 3.5 AJAX, ASP.NET 2.0 MVP Hacks and Tips," and "XML for ASP.NET Developers." Read Dan's blog here.

comments powered by Disqus

Featured

  • AI for GitHub Collaboration? Maybe Not So Much

    No doubt GitHub Copilot has been a boon for developers, but AI might not be the best tool for collaboration, according to developers weighing in on a recent social media post from the GitHub team.

  • Visual Studio 2022 Getting VS Code 'Command Palette' Equivalent

    As any Visual Studio Code user knows, the editor's command palette is a powerful tool for getting things done quickly, without having to navigate through menus and dialogs. Now, we learn how an equivalent is coming for Microsoft's flagship Visual Studio IDE, invoked by the same familiar Ctrl+Shift+P keyboard shortcut.

  • .NET 9 Preview 3: 'I've Been Waiting 9 Years for This API!'

    Microsoft's third preview of .NET 9 sees a lot of minor tweaks and fixes with no earth-shaking new functionality, but little things can be important to individual developers.

  • Data Anomaly Detection Using a Neural Autoencoder with C#

    Dr. James McCaffrey of Microsoft Research tackles the process of examining a set of source data to find data items that are different in some way from the majority of the source items.

  • What's New for Python, Java in Visual Studio Code

    Microsoft announced March 2024 updates to its Python and Java extensions for Visual Studio Code, the open source-based, cross-platform code editor that has repeatedly been named the No. 1 tool in major development surveys.

Subscribe on YouTube