Search code examples
asp.net-coreroutes.net-coreasp.net-routingasp.net-core-2.1

Asp.net Core 2.1 Routing Issue


I tried some routing in asp.net core 2.1 and facing a issue with routing...

Startup.cs -> Configure Method

app.UseMvc(routes => {
            routes.MapRoute(
                name: "default", 
                template: "{Controller=Demo}/{Action=Index}/{id?}");
        });

DemoController.cs

[Route("demo")]
public class DemoController : Controller
{
    [Route("")]
    [Route("index")]
    [Route("MyDemoPage")]
    [Route("~/")]
    public IActionResult Index()
    {
        return View();
    }

    [Route("demo2/{id}")]
    [Route("cj/{id}")]
    public IActionResult Demo2(int id)
    {
        ViewBag.id = id;
        return View("Demo2");
    }

    [Route("demo3/{id1}/{id2}")]
    [Route("cc/{id1}/{id2}")]
    public IActionResult Demo3(int id1,string id2)
    {
        ViewBag.id = id1;
        ViewBag.id2 = id2;
        return View("Demo3");
    }
}

Index.cshtml Page

@*[Route("demo2/{id}")]*@
<br />
<a asp-controller="demo" asp-action="demo2" asp-route-id="123">Demo2</a>
@*Above Tag renders :> <a href="/demo/cj/123">Demo2</a>*@ Link 1
<br />
@*[Route("cj/{id}")]*@
<br />
<a asp-controller="demo" asp-action="cj" asp-route-id="07">Demo2 via route CJ</a>
@*Above Tag renders :> <a href="/demo/cj/07">Demo2 via route CJ</a>*@ Link 2

<br />
@*[Route("demo3/{id1}/{id2}")]*@
<br />
<a asp-controller="demo" asp-action="demo3" asp-route-id1="123" asp-route-id2="P001">Demo3</a>
@*Above Tag renders :> <a href="/demo/cc/123/P001">Demo3</a>*@ Link 3
<br />
@*[Route("cc/{id1}/{id2}")]*@
<br />
<a asp-controller="demo" asp-action="cc" asp-route-id1="123" asp-route-id2="abc">Demo via CC</a>
@*Above Tag renders :> <a href="/demo/cc?id1=123&id2=abc">Demo via CC</a>*@ Link 4

Demo2.cshtml

 @*[Route("index")]*@
    <br />
    <a asp-controller="demo" asp-action="index">Index Page</a>
    @*Above Tag renders :> <a href="/demo/MyDemoPage">Index Page</a>*@ Link 5
    <br />
    @*[Route("MyDemoPage")]*@
    <br />
    <a asp-controller="demo" asp-action="MyDemoPage">Index Page via MyDemoPage 
    Route</a>
    @*Above Tag renders :> <a href="/demo/MyDemoPage">Index Page via MyDemoPage 
    Route</a>*@ Link 6

Github Link

I am confuse why did Link 4 & Link 3 are different in index.cshtml and Link 5 & Link 6 rendered same href Please help...


Solution

  • For the reason that different result for Link 5 & Link 6, they are generated by different rules.

    For URL generation, RouteCollection call GetVirtualPath to use IRouter to generate the url. There are two default irouter, Microsoft.AspNetCore.Mvc.Internal.AttributeRoute and Microsoft.AspNetCore.Mvc.Internal.MvcRouteHandler.

    For asp-action="index", it is handled by AttributeRoute and GetMatches will order the MyDemoPage before index. You could check OutboundMatchResultComparer to check compare logic. If you change [Route("MyDemoPage")] to [Route("myDemoPage")], it will generate /demo/index.

    For asp-action="MyDemoPage", GetMatches return zero count for IList<OutboundMatchResult>. Then, it goes to MvcRouteHandler, and call RouteBase. _binder.BindValues(values.AcceptedValues); will generate /demo/MyDemoPage.

    The different result for GetMatches is controlled by whether value for asp-action exist in the Controller Action. For your scenario, Index is exist, but MyDemoPage not, there is no corresponding method for MyDemoPage.

    Update

    One more time, the key different result is caused by whether the action is real exist in the Controller method.

    For asp-action="cc", there is no cc action in DemoController, it goes with Controller MVC Binder, and format as /demo/cc?id1=123&id2=abc.

    For asp-action="demo3", there is action called demo3, it is generated by Router Attribute Binder, and will generate _template = "demo/cc/{id1}/{id2}" and _template = "demo/demo3/{id1}/{id2}" in order. For the order, it will return /demo/cc/123/P001.