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?
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.
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 }
);
}
}
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.