How to change the request timeout for WCF RIA Services

My teammate, Jason Cooke, put together this great article on changing the timeout in RIA Services. Hope you find it helpful.

Change Timeouts for WCF RIA Services

WCF RIA Services specifies default timeouts for its endpoints, so you can be sure that all requests complete in a reasonable time, either with success, or a timeout error:

The HTTP request to 'https://<your URL>' has exceeded the allotted timeout. The time allotted to this operation may have been a portion of a longer timeout.

This error comes from the client's underlying WCF endpoint when a long-running request takes longer than the endpoint's SendTimeout, which is one minute by default.

If you get this error, first consider restructuring the operation to enable it to finish sooner. For example, split the operation into multiple parts, or just kick off the operation and poll for completion.

You don't need to change your design, though, because you can extend the client timeout values in RIA Services. The key is to get the endpoint for your domain service (as shown in RIA Services Authentication Out-Of-Browser), and change the timeouts on the endpoint's binding.

   /// <summary>
  /// Utility class for changing a domain context's WCF endpoint's
  /// SendTimeout. 
  /// </summary>
  public static class WcfTimeoutUtility
  {
    /// <summary>
    /// Changes the WCF endpoint SendTimeout for the specified domain
    /// context. 
    /// </summary>
    /// <param name="context">The domain context to modify.</param>
    /// <param name="sendTimeout">The new timeout value.</param>
    public static void ChangeWcfSendTimeout(DomainContext context, 
                                            TimeSpan sendTimeout)
    {
      PropertyInfo channelFactoryProperty =
        context.DomainClient.GetType().GetProperty("ChannelFactory");
      if (channelFactoryProperty == null)
      {
        throw new InvalidOperationException(
          "There is no 'ChannelFactory' property on the DomainClient.");
      }

      ChannelFactory factory = (ChannelFactory)
        channelFactoryProperty.GetValue(context.DomainClient, null);
      factory.Endpoint.Binding.SendTimeout = sendTimeout;
    }
  }

Pass the domain context for the long-running operation and the new value for the send timeout to the ChangeWcfSendTimeout method, and you are good. You cannot change the binding after the endpoint is used, so the best place to call this method is in the domain context's partial OnCreated method, like this:

 namespace SampleNamespace.Web.Services
{
  public partial class MyDomainContext
  {
    partial void OnCreated()
    {
      TimeSpan tenMinutes = new TimeSpan(0, 10, 0);
      WcfTimeoutUtility.ChangeWcfSendTimeout(this, tenMinutes);
    }
  }
}

It’s important to make sure the namespaces match when implementing partial methods. The code in this sample should be included in your client project (here it has the name SampleNamespace) and the domain service is SampleNamespace.Web.Services.MyDomainService.