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

  • Microsoft Revamps Fledgling AutoGen Framework for Agentic AI

    Only at v0.4, Microsoft's AutoGen framework for agentic AI -- the hottest new trend in AI development -- has already undergone a complete revamp, going to an asynchronous, event-driven architecture.

  • IDE Irony: Coding Errors Cause 'Critical' Vulnerability in Visual Studio

    In a larger-than-normal Patch Tuesday, Microsoft warned of a "critical" vulnerability in Visual Studio that should be fixed immediately if automatic patching isn't enabled, ironically caused by coding errors.

  • Building Blazor Applications

    A trio of Blazor experts will conduct a full-day workshop for devs to learn everything about the tech a a March developer conference in Las Vegas keynoted by Microsoft execs and featuring many Microsoft devs.

  • Gradient Boosting Regression Using C#

    Dr. James McCaffrey from Microsoft Research presents a complete end-to-end demonstration of the gradient boosting regression technique, where the goal is to predict a single numeric value. Compared to existing library implementations of gradient boosting regression, a from-scratch implementation allows much easier customization and integration with other .NET systems.

  • Microsoft Execs to Tackle AI and Cloud in Dev Conference Keynotes

    AI unsurprisingly is all over keynotes that Microsoft execs will helm to kick off the Visual Studio Live! developer conference in Las Vegas, March 10-14, which the company described as "a must-attend event."

Subscribe on YouTube