Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Task async controller method does not hit

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?

like image 385
Will Jenkins Avatar asked Nov 26 '13 15:11

Will Jenkins


Video Answer


2 Answers

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.

like image 148
spender Avatar answered Sep 18 '22 13:09

spender


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 }
        );
    }
}
like image 23
Panagiotis Kanavos Avatar answered Sep 17 '22 13:09

Panagiotis Kanavos