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.
Comments
Anonymous
November 04, 2010
Thanks.Anonymous
November 07, 2010
Hi Kyle, I tried this but didn't succeed. Maybe I'm missing something... There are two errors I get:
- Type of the first parameter in ChangeWcfSendTimeout method is DomainContext and compiler complains about the datatype of DomainService being passed as "this".
- The second error is about missing declaration of partial OnCreated() method. Maybe I'm missing some reference... I don't know... still fresh in WCF RIA Services world :)
Anonymous
November 07, 2010
@anilmujagic It may not be entirely clear in the post. This is something you'd write in a partial class on the Silverlight side. I'll update the sample to make it less confusing.Anonymous
November 07, 2010
Thanks, looking forward to it.Anonymous
December 06, 2010
Hi Kyle, Have implemented this logic client-side, but get the following compiler warnings: Warning 275 The type 'Analytics.Web.PublicationContext' in 'C:DevelopmentAnalyticssourceWebPortalBusiness.ClientContentLoadersPublicationService.cs' conflicts with the imported type 'Analytics.Web.PublicationContext' in 'C:DevelopmentAnalyticssourceInsurer.Analytics.CommonbinDebugInsurer.Analytics.Common.dll'. Using the type defined in 'C:DevelopmentAnalyticssourceWebPortalBusiness.ClientContentLoadersPublicationService.cs'. The namespaces of the server-side DomainService and client-side partial class match but the partial class is seen as a separate object and not part of the imported DomainContext. Any ideas? Thanx, ChrisAnonymous
December 06, 2010
@Chris It sounds like you're defining the PublicationService in one assembly (Insurer.Analytics.Common) and the partial class in another (Business.Client). For this solution to work, the partial class must be defined in the same assembly as the generated DomainContext. In this case, it looks like you want to define it in Insurer.Analytics.Common.Anonymous
December 07, 2010
Thanx Kyle, you were spot on with that. Much appreciated. Regards, ChrisAnonymous
March 21, 2011
Kyle or Chris Can you guys post the steps to create this additional class for those of us RIA newies!!!Anonymous
April 04, 2011
SBe did they answer you? I need the same answer you requested.Anonymous
March 06, 2012
Hi Kyle, This is a very informative post, I have implemented this successfully, and wanted to add for anyone listening that for me, this coupled with extending the ORM's timeout covered all timeout issues. My ORM is entity framework so by doing this: public List<entity> getentities() { this.ObjectContext.CommandTimeout = 180; I have my ORM (Entity framework), and service layer extended, so no timeouts anymore:-)Anonymous
May 24, 2012
Can you post a clearer example of where in the client code these two snippets should go? I can't get these to work at all. Can't get the DomainContext to resolveAnonymous
September 27, 2012
Thanks for this solution! It was exactly what we needed to handle long-running stored-proc commands issued through our ObjectContext without continually polling for the results. I had tried the ObjectContext.CommandTimeout but it had no effect (possibly because we are using the Oracle Data Providers and they are not supported?) Overriding the default SendTimeout value on the endpoint worked. For those that may still have trouble: Create the partial DomainContext class in your Silverlight client project, giving it the same namespace as the other part of the partial class; that other part is the auto-generated class from the DomainService." You can find the auto-generated partial by clicking on your Silverlight client project in the solution explorer and clicking the Show All Files toolbar button. The class file will be in the Generated_Code folder and have the sufix .g.cs. Look for the partial class that derives from DomainContext; you should see a partial method, "partial void OnCreated();" in a region called Extensibility Method Definitions. This method is what you override in your own partial DomainContext class, as Kyle describes (sorry, not sure if 'override' is the correct term when dealing with partial classes... maybe 'double-up' would be better.)Anonymous
March 02, 2013
This is exactly I am looking for, but in vb.net. I am not able to convert it into VB.net code, OnCreated method gves error also other namespaces missing, if feasible please provide Solution in VB.netAnonymous
September 03, 2013
The comment has been removed