1

I have googled for this and have managed to find several links explaining the concept of Async HTTP Requests in C# and Web Api 2. However I failed to get any working examples of the same.

Just to clear the air, my requirement is as below. When the client calls an API (which does long running processing), it must returns HTTP 202 (Accepted) as response almost immediately, and continue processing in the background. I am clear till this point. Below is my sample code as to how I have implemented the same. Where I am stuck is when this long processing task is complete in the background it must fire a callback to the same client and return with an HTTP 200 response. It may be possible that while the long processing task was executing in the background, the client has issued another concurrent request with different values.

Can anyone point me in the right direction. Is this possible only through code or would there be any settings to be implemnted at the IIS level. Appreciate your time and help in this.

Thanks to everyone in advance.

My Code so far.

public HttpResponseMessage Execute(string plugin, string pluginType, string grid, string version)
    {
        try
        {
            var type = this.LoadPlugin(plugin, pluginType, version);

            if (type != null)
            {
                var method = type.GetMethod("Execute");

                if (method != null)
                {
                    new Task(() =>
                    {
                        // This line will take long to execute.
                        var filepath = method.Invoke(Activator.CreateInstance(type), new object[1] { grid });

                        // After this line it must invoke a callback to the client with the response as "filepath" and HTTP status code as 200 
                        type = null;                            
                    }).Start();
                }
                else
                {
                    return new HttpResponseMessage(HttpStatusCode.ServiceUnavailable);
                }
            }
            else
            {
                return new HttpResponseMessage(HttpStatusCode.ServiceUnavailable);
            }
        }
        catch (Exception ex)
        {
            return new HttpResponseMessage(HttpStatusCode.InternalServerError);
        }

        return new HttpResponseMessage(HttpStatusCode.Accepted);
    }

    private Type LoadPlugin(string plugin, string pluginType, string version)
    {
        Assembly assembly;

        Type returnValue = null;

        var pluginFile = new DirectoryInfo(this._pluginPath).GetFiles("*.dll")
                                                            .Where(file => FileVersionInfo.GetVersionInfo(file.FullName).OriginalFilename.ToUpper().Contains("TRANSFORMATION." + plugin.ToUpper()))
                                                            .OrderByDescending(time => time.LastWriteTime).FirstOrDefault();

        if (pluginFile != null)
        {
            assembly = Assembly.LoadFrom(pluginFile.FullName);

            AppDomain.CurrentDomain.Load(assembly.GetName());

            returnValue = assembly.GetType("Transformation.Plugins." + pluginType);

            assembly = null;
        }

        return returnValue;
    }
  • You can't send multiple Response for a single Request as it will violate the HTTP standard. However you may write custom code to send some response for the particular event. You may also consider Response.Flush()- https://msdn.microsoft.com/en-us/library/system.web.httpresponse.flush(v=vs.110).aspx – Souvik Ghosh Sep 29 '16 at 06:28

1 Answers1

0

I think you can solve this issue making your Web API method async:

public async Task<HttpResponseMessage> Execute(string plugin, string pluginType, string grid, string version)
{
    // Your code here
}

Also, your task's invoke should be with await keyword, something like this:

await Task.Run(() =>
{
    // Yor code here
});

You can have multiple await inside of your async method.

Let me know if this answer is useful.

H. Herzl
  • 3,030
  • 1
  • 14
  • 19
  • I have tried this also. But after the await Task.Run() is finished executing, it does not return the response; cos the response was already sent even before Task.Run() started. So basically, there must be a callback method which must be get executed after Task.Run() is finished. – Harshit Gandhi Sep 29 '16 at 08:44
  • I've used this async way with angular app with lot of callls and I didn't have trouble, how do you call your api from client ? – H. Herzl Sep 29 '16 at 19:45
  • I need to emulate your scenario for provide a solution, can you provide me the required code for this issue? – H. Herzl Sep 29 '16 at 21:59