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

  • Hands On: New VS Code Insiders Build Creates Web Page from Image in Seconds

    New Vision support with GitHub Copilot in the latest Visual Studio Code Insiders build takes a user-supplied mockup image and creates a web page from it in seconds, handling all the HTML and CSS.

  • Naive Bayes Regression Using C#

    Dr. James McCaffrey from Microsoft Research presents a complete end-to-end demonstration of the naive Bayes regression technique, where the goal is to predict a single numeric value. Compared to other machine learning regression techniques, naive Bayes regression is usually less accurate, but is simple, easy to implement and customize, works on both large and small datasets, is highly interpretable, and doesn't require tuning any hyperparameters.

  • VS Code Copilot Previews New GPT-4o AI Code Completion Model

    The 4o upgrade includes additional training on more than 275,000 high-quality public repositories in over 30 popular programming languages, said Microsoft-owned GitHub, which created the original "AI pair programmer" years ago.

  • Microsoft's Rust Embrace Continues with Azure SDK Beta

    "Rust's strong type system and ownership model help prevent common programming errors such as null pointer dereferencing and buffer overflows, leading to more secure and stable code."

  • Xcode IDE from Microsoft Archrival Apple Gets Copilot AI

    Just after expanding the reach of its Copilot AI coding assistant to the open-source Eclipse IDE, Microsoft showcased how it's going even further, providing details about a preview version for the Xcode IDE from archrival Apple.

Subscribe on YouTube

Upcoming Training Events