Task async controller method does not hit

2019-05-08 05:21发布

问题:

So, we've got an MVC project that has been upgraded through the different versions of MVC from 1 through to 4.

Now we have a controller method:

public async Task<ActionResult> IndexAsync()

so if we go to http://somedomain.xyz/WhicheverController or http://somedomain.xyz/WhicheverController/Index, we are greeted with a 404.

http://somedomain.xyz/WhicheverController/IndexAsync routes to the method just fine.

What's gone wrong with our routing?

回答1:

I believe that your example will work if you derive your Controller from AsyncController instead.

public class MyController:AsyncController
{
    public async Task<ActionResult> IndexAsync()
    {
       return View(); //view called "Index.cshtml", not "IndexAsync.cshtml"
    }
}

So now you can hit ~/My/Index without the Async suffix, despite Async appearing in the controller name.

This is a relic from the previous MVC asynchronous controller method, and usually required an IndexComplete method to work, but with Task based async controller method, the matching XxxxComplete method is not required, but the Async convention is observed.

The actual implementation of AsyncController is rather sparse:

public abstract class AsyncController : Controller
{
}

So somewhere in the MVC stack, the type of the controller is tested, and special routing magic is turned on.



回答2:

There is no convention that maps asynchronous actions to methods with the Async suffix. If you want to use the Async suffix in an action's name, you will have to modify your route.

Simply changing your method's return type to async Task<ActionResult> is enough to execute the action asynchronously.

The Async suffix is simply a naming convention. It isn't expected or enforced by any of the MVC frameworks.

Example

The following action works asynchronously using the default routing

public class HomeController : Controller
{
    public async Task<ActionResult> Index()
    {
        await Task.Delay(1000);
        ViewBag.Message = "Modify this template to jump-start blah .. blah";

        return View();
    }
    ...
}

public class RouteConfig
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Home", action = "Index", 
                            id = UrlParameter.Optional }
        );
    }
}


回答3:

Routing works just fine, in asp.net mvc 5 you don't need Async suffix for action anymore and you should remove it.

This convention was needed just for linking two actions that execute one job asynchronously (action method and action result). With new asyncronous model for in asp.net mvc 5 you don't need this Async convention anymore. Just like inheriting from AsyncController.