Avoid client timeout on WebAPI call

If a WebAPI service takes a long time to complete, the caller, the client side, may timeout waiting for a response. There are several options to solve this issue, you can increase the timeout limit on the client side and web server side, or use a more persistent connection method like WebSocket and SignalR.

Here I propose a different way to avoid the timeout issue that allows the clients side to proactively check the result instead of passively waiting. The idea is pretty intuitive – since the client side times out on waiting for a response, why don’t just disconnect and check back the result later? So the solution is to disconnect with the client side as soon as the request is received and a WebAPI service is provided to enable client to check for the status of the processing. This way the client does not need to keep the connection open until the processing completes or times out. It can simply calls back every 5 seconds to check the result of the processing.

Here I am going to provide some sample code on how to achieve this. First, we create a Task class

public class Task
{
   public string TaskID;
   public Request Request;
   public Status Status;
   public Result Result;

   public void Execute(){
   // Do all sort of calculation and processing here
   // When done, sets the Status of the task to Finished.
   }
}

We then create a class to store tasks and to handle creation, retrieval, and deletion of tasks.

public class TaskManager
{
   private static List<Task> _TaskList = new List<Task>();
   // Create a new instance of Task object
   // and start a new thread to run this task
   public static Result CreateNewTask(Request request){
      var task = New Task(){
                TaskID =  System.Guid.NewGuid().ToString();
                .....
                };
      _TaskList.add(task);
      Thread thread = new Thread(task.Execute);
      task.Status = Status.Processing
      thread.start;
   }
   // This is also useful for purging tasks
   public static void RemoveTask(string taskID)
   public static Task GetTaskByID(string taskID)
}

Up to this point, we have our ‘backend’ built. Now we are going to create a WebAPI method to accept the request from the client side and a method for client side to check a task’s status:

[HttpPost]
public Result ProcessRequest(Request request){
// Submit a request which will be created as a task
// Return the TaskID back to client
}

[HttpGet]
public Result CheckStatus(String taskID){
// Call this every few seconds to check result
}

In this post I shared an idea to avoid client side timeout when calling WebAPI. We chose an approach that enables client side to check the result actively. Although it makes the client side a bit more complex, it is a reliable way to handle WebAPI calls that run a long time and also provides much more flexibility to the client side.

Use Message security on WCF service behind a SSL handler

Configuring WCF web service’s security is just tedious. Microsoft has been trying to make it simple by removing many configuration settings in .NET 4.5 but it could still get messy if you need to touch the security part – There are many bindings and there are Message, Transport, and TransportWithMessageCredentials security modes, each with their own client credential types, not mentions all those authentication modes for Custom Bindings such as AnoymousForCertificate, IssuedTokenForCertificate, IssuedTokenOVerTransport, etc.

Developers are developing WCF web service on the platform from Microsoft. They are the users of the platform in this sense. It’s supposed to be user friendly and intuitive. But I found it is quite difficult to select the right security configuration in different scenarios. Even after you read the documentation from Microsoft carefully, you sill have a very limited idea on how these security modes differentiate from each other.

This post is aimed to cover one small scenario of using WCF security – using a WCF web service with cert-based Message security behind a front-end SSL handler. Often times, your web servers are behind a load balancer that handles all SSL requests and pass in HTTP requests to your IIS. Below is diagram showing the infrastructure.

8-8-2014 4-17-55 PM

At first glance, it seems pretty straightforward – Transport security mode covers SSL security, Message security mode handles message encryption. Hey there is a security mode just for the two modes combined: TransportWithMessageCredentials . We should be able to just use that on both client and service side to achieve what we want, right? However, you just can’t be so optimistic in the world of software development.

This configuration won’t working. First of all, since the service is not really receiving HTTPS requests, Transport mode should not be used. We just need Message security. So below is the correct configuration on service side.

<wsHttpBinding>
     <binding name="WsBindingConfigration">
     <security mode="Message">
      <message clientCredentialType="Certificate" negotiateServiceCredential="true"
algorithmSuite="Default" establishSecurityContext="false"/>
     </security>
    </binding>
  </wsHttpBinding>

The client side is where it gets tricky. I can’t really explain why TransportWihtMessageCredential doesn’t work. Something goes wrong under the hood. But here is the configuration worked for me. Use MutualSSLNegotiated mode and CustomBinding!

<customBinding>
        <binding name="customBinding_CertAuth_ClientService">
           <security authenticationMode="MutualSslNegotiated">
           </security>
           <httpsTransport authenticationScheme="Anonymous"
proxyAuthenticationScheme="Anonymous" useDefaultWebProxy="true">
           </httpsTransport>
        </binding>
</customBinding>

It took me a long while to research and trial and error to finally figure this out. Many development teams don’t have the time to mirror the environments of their clients, which makes finding and troubleshooting issues like this difficult. But hopefully this post can help you out.