We are consuming wcf services on the silverlight application trough creating proxies using ChanellFacotry.
The Operation and Data contracts are exposed to silverlight trough assembly, which is consist of shared files from serverside Data and Operation contract libriary. (omg I hope you understand what I am saying).
So server and client are using same operation and data contracts.
Silverlight wcf client lib has a restriction to not be able to call wcf methods synchronously, as you know, so shared operation contract file has to expose asyn versions of each operation.
Writing async WCF service would make some sense if they were not containing blocking operations, but as we are using EF, asyncrhony is achieved by delegating blocking work to thread pool. This is what WCF do for synch methods anyway. And this fact makes me want to tear my eyes out (#@%!^%!@%).
Our project consultant has power to not allow generate dynamic proxies on the client to call synch operation contract methods (google Yevhen Bobrov Servelat Pieces if you are interested). So we have to write senseles implementations of async methods on serverside, without any performance gain (blocking calls as you remember).
Is it possible to call wcf web service synchronous method from silverlight using its data contract?
Have you ever faced this problem before, if so how did you solve it?
At the momment I am looking forward for generating async contracts for client side only using serverside contracts as a transformation source. Maybe there are some t4 template that can nicely do it for me?
Sorry for the wall of text, just to mix some code to my question, this is how async contract implementation looks at the momment:
/// <summary>
/// Subscribes to users of the specified organization.
/// </summary>
/// <param name="organizationId">The organization id.</param>
public void Unsubscribe(int organizationId)
{
var clientId = this.OperationContext.GetClientId();
if (string.IsNullOrEmpty(clientId))
{
return;
}
this.InternalUnsubscribe(organizationId, clientId);
}
/// <summary>
/// Begins an asynchronous operation to Unsubscribe.
/// </summary>
/// <param name="organizationId">The organization id.</param>
/// <param name="callback">The callback.</param>
/// <param name="passThroughData">The pass through data.</param>
/// <returns>
/// An implementation of <see cref="IAsyncResult"/> that provides access to the state or result of the operation.
/// </returns>
public IAsyncResult BeginUnsubscribe(int organizationId, AsyncCallback callback, object passThroughData)
{
var clientId = this.OperationContext.GetClientId();
if (string.IsNullOrEmpty(clientId))
{
return null;
}
var asyncResult = new VoidAsyncResult(callback, passThroughData);
Task.Factory.StartNew(() =>
{
try
{
this.InternalUnsubscribe(organizationId, clientId);
asyncResult.SetAsCompleted(false);
}
catch (Exception ex)
{
asyncResult.SetAsCompleted(ex, false);
}
});
return asyncResult;
}
/// <summary>
/// Ends an existing asynchronous operation to Unsubscribe.
/// </summary>
/// <param name="result">The <see cref="IAsyncResult"/> provided by the BeginUnsubscribe operation.</param>
public void EndUnsubscribe(IAsyncResult result)
{
var response = result as VoidAsyncResult;
if (response != null)
{
response.EndInvoke();
}
}
You do not need to write the WCF service to be Async. You simple need to make a ServiceContract for your service that defines the Async methods. Here's a quick example
Now use IMyServiceAsync with your ChannelFactory and everything should work.