2

I'm trying to encapsulate some features in my application, for example instead of writing these codes in every POST action method:

var baseUrl = context.HttpContext.Request.Url.Scheme + "://" + context.HttpContext.Request.Url.Authority +
context.HttpContext.Request.ApplicationPath.TrimEnd('/') + "/signalr";
var hubConnection = new HubConnection(baseUrl);
var notification = hubConnection.CreateHubProxy(hubName: HubName);
await hubConnection.Start();
await notification.Invoke(MethodName); 
return RedirectToAction("TicketList", "Ticket")

I have made something like this using extension method and custom actionresult:

return RedirectToAction("TicketList", "Ticket").WithSendNotification("notificationHub", "sendNotification");

In order to do that I've created a custom action result and I put the logic inside ExecuteResult method:

public async override void ExecuteResult(ControllerContext context)
{
    var baseUrl = context.HttpContext.Request.Url.Scheme + "://" + context.HttpContext.Request.Url.Authority +
    context.HttpContext.Request.ApplicationPath.TrimEnd('/') + "/signalr";
    var hubConnection = new HubConnection(baseUrl);
    var notification = hubConnection.CreateHubProxy(hubName: HubName);
    await hubConnection.Start();
    await notification.Invoke(MethodName);
    InnerResult.ExecuteResult(context);
}

But I get following error:

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.

Now my question is that Can void async method be used in custom action result?

Update: ASP.NET 5 has this ability, Means action result now have ActionResult.ExecuteResultAsync in addition to ActionResult.ExecuteResult. Now I want to know How can we implement this ability in MVC 5.0?

Sirwan Afifi
  • 10,654
  • 14
  • 63
  • 110
  • 1
    Not very clear why you did not want to just refactor method in controller... But here is long question and answer why you really should not be doing that (including the way to do fire-and-forget/crash as you trying to do) - http://stackoverflow.com/questions/17659603/async-void-asp-net-and-count-of-outstanding-operations – Alexei Levenkov Sep 05 '15 at 05:48

2 Answers2

1

How can we implement this ability in MVC 5.0?

You can't.

ASP.NET vNext, as you noticed, is rewritten from the ground up with async in mind. The current version of ASP.NET (particularly MVC) has a few rough edges where it's simply impossible to use async.

Stephen Cleary
  • 437,863
  • 77
  • 675
  • 810
1

As Stephen said, I can't use async ability inside ExecuteResult in MVC 5.0. Since my goal was a little bit refactoring I had to use ContinueWith:

public override void ExecuteResult(ControllerContext context)
{
    //....
    hubConnection.Start().ContinueWith(task =>
    {
         if (task.IsCompleted)
         {
             notification.Invoke(MethodName);
         }
    });
    InnerResult.ExecuteResult(context);
}

Now it works like a charm.

Community
  • 1
  • 1
Sirwan Afifi
  • 10,654
  • 14
  • 63
  • 110