Asynchronous Web Service in ASP.NET MVC

I am writing an ASP.NET MVC 5 application that, among other things, uses web services to receive / process some data.

The application data stream is as follows: MVC Action -> Service B -> ExtSvc, which is an asynchronous web service wrapper

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 stream throws an error

The first exception of type "System.InvalidOperationException" exception occurred in System.Web.dll

: . . , , <% @Page Async = "true" % > . "", ASP.NET. , .

ExtSvc: this.Service.ProcessRequestAsync(request, taskCompletionSource); ProcessRequestAsync void :

"", ASP.NET

, GetResponse MVC ( async/await), B, ExtSvc , .

:

B (- , ), Task<Response> Response, , async/await , ?

+4
2

ProcessRequestAsync void, async void. EBAP API. EBAP AsyncOperationManager/AsyncOperation, , , do SynchronizationContext ( MSDN SynchronizationContext).

, , , ASP.NET ( ) "whoa, there, fella. - ! !"

, - , . , B.Update B.UpdateAsync. , IB.Update - IB.UpdateAsync . , .

. Task.Run @neleus - ASP.NET SynchronizationContext, "" , , " " , HttpContext.Current . () new SynchronizationContext() , ASP.NET SynchronizationContext, , ASP.NET ASP.NET SynchronizationContext .

, ; , . Task<ActionResult> Task.FromResult, : return Task.FromResult<ActionResult>(View(...)); ASP.NET , ( ).

, , , sync-over-async (this.ExtSvc.UpdateRequest(arguments).Result), , ( , Task.Run). , , , .

+3

, - ,

this.Service.ProcessRequestAsync(request, taskCompletionSource);

SynchronizationContext's OperationStarted, , .

ThreadPoolSynchronizationContext

public async Task<ActionResult> GetResponse(int id)
{
     //some logic
     await Task.Run(() => { B.Update(id); });
     //some logic
     return View(...);
}

.

+1

All Articles