I am writing an ASP.NET MVC 5 application which among others uses web services to get/process some the data.
The data flow of the app is following: MVC Action -> Service B -> ExtSvc which is async wrapper of a web service
Here are some examples:
public class ExtSvc
{
//Convert Event based async pattern to task based async pattern:
private Task<Response> ProcessExtRequestAsync(Request request)
{
TaskCompletionSource<Response> taskCompletionSource =
AsyncServiceClientHelpers.CreateSource<Response>(request);
ProcessRequestCompletedEventHandler handler = null;
handler =
(sender, e) =>
AsyncServiceClientHelpers.TransferCompletion(
taskCompletionSource,
e,
() => e.Result,
() => this.Service.ProcessRequestCompleted -= handler);
this.Service.ProcessRequestCompleted += handler;
try
{
this.Service.ProcessRequestAsync(request, taskCompletionSource);
}
catch (Exception)
{
this.Service.ProcessRequestCompleted -= handler;
taskCompletionSource.TrySetCanceled();
throw;
}
return taskCompletionSource.Task;
}
//Usage:
public async Task<Response> UpdateRequest(some arguments)
{
//Validate arguments and create a Request object
var response = await this.ProcessExtRequestAsync(request)
.ConfigureAwait(false);
return response;
}
}
Class B is the one that uses ExtSvc in a synchronous way
public class B
{
public ExtSvc service {get; set;}
public Response Update(arguments)
{
//some logic
var result = this.ExtSvc.UpdateRequest(arguments).Result;
//some logic
return result
}
}
Finally the MVC action (also synchronous)
public ActionResult GetResponse(int id)
{
//some logic
B.Update(id);
//some logic
return View(...);
}
The described flow throws an error
A first chance exception of type 'System.InvalidOperationException' occurred in System.Web.dll
Additional information: An asynchronous operation cannot be started at this time. Asynchronous operations may only be started within an asynchronous handler or module or during certain events in the Page lifecycle. If this exception occurred while executing a Page, ensure that the Page is marked <%@ Page Async="true" %>. This exception may also indicate an attempt to call an "async void" method, which is generally unsupported within ASP.NET request processing. Instead, the asynchronous method should return a Task, and the caller should await it.
on the following line of ExtSvc : this.Service.ProcessRequestAsync(request, taskCompletionSource);
ProcessRequestAsync
is a void method
So it corresponds to:
This exception may also indicate an attempt to call an "async void" method, which is generally unsupported within ASP.NET request processing
I know that converting GetResponse MVC action to asynchronous (by using async/await) and also converting the B class that actually uses ExtSvc to be asynchronous resolves the issue.
BUT my questions is:
If I can't change the signature of B class (because of an interface it implements) to return Task<Response>
instead of Response
it basically means that I can't use async/await on it so how this issue could be resolved?