-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Description
this is not a bug, but it should be, and if you guys still think it should be the designed behaviors please make a vote here
Describe the issue
this is my second time to report this aspnet/Mvc#7046, previously I think it may be fixed by the Endpoint-Routing, but it doesn't.
we create the MVC which we try to separate the View and Controller , and they both follow the contract which is the Model,
but this issue cause the View must know about the controller/action and it's routing metadata.
think follow controller:
// [Area(null)] //no area
[HttpGet("/[controller]/{a:int}-{b:int}")] // controller "blog" with attribute routing
[HttpGet("/[controller]/{a:int}-0")]
public IActionResult Index(int a, int b, int c)
{
return view();
}
[Area("foo")] // controller "blog" with `.MapControllerRoute(template)`
public IActionResult Index(int a, int b, int c, int d)
{
return view();
}now when you routing in the view, you must know who is the controller and where is it, if you don't, then it's wrong
<a asp-action="Index" asp-controller="Blog" asp-route-a="1" >this link is wrong </a>because if you in area "foo" , it not point to foo area, instead it point to area null so it will be /blog/1-0 ,
if you in area "null" , then it also point to /blog/1-0 , but if you in /blog/5-3 it will be /blog/1-3 so how can your view know where it is ? so, to correct the link you need to write
<a asp-action="Index" asp-controller="Blog" asp-route-a="1" asp-route-b="null" >
the view must know your controller add a `b` route variable
</a>To Reproduce
https://github.com/John0King/UrlGenTest it's the old repo , but it explain everything
what cause it
- Attribute routing has higher priority, it's now all about endpoint so why it still has difference (eg. with tempalte
{controller=Home}/{action=Index}/{id?}map to "HomeController.Index" with[Route("/")][Route("[controller]/[action]/["id"]")]) others with[Route("[controller]/[action]/{id?}")](the endpoint route-data) on the action , but this one is not the main issue, it the attribute routing with higher priority is OK for this issue, it's jut will some api override the MVC 's path (because api normally we hard code it's api path like/api/foo/getlistinstead of generate it ) - main issue route data not specific what data will be keep and what data will be drop, current it depend on current route and current
endpoint, it cause our view must know about the action's routing data
how to fix
the Attribute-Routing already give us answer to know what kind of routing data need to keep, for example [controller]/[action]/{id} the controller and action will be keep and id will be drop for [area]/[controller]/[action]/{a}/{b} the a and b will be drop, the route value with [ ] is called framework route variables, when you write the view, the view must know those variables but it do not know the route variables with { }, here is the framework route variables https://github.com/John0King/UrlGenTest/blob/8f4ad7aa6ae9c5552845a0fd27100149c63e00b1/Views/Shared/NewsTest.cshtml#L91-L96
we need to let the IUrlHelper to know the ActionContext.ActionDescriptor.RouteValues and keep all the route value if we do not override it we can use string.Empty to override the empty "area" route data
is there a break change after fix
theoretically yes, but actually no. because if your app has correct link , then the link must be correct : for example
case 1:
Non-area has attribute route, and area has conventional route , you must add area so the link in area is correct, and if someone want to goto non-area, then the empty area must be set so it can make conventional route to conventional route to work.
case 2:
from area to non-area with null , it won't work even now, because null is the default value of RouteContext, so it must use string.Empty , and it will work after the change too.
case 3:
same page route like {a}-{b}, to make link link correct , you must specific both a and b to make the link corrent, otherwise even developer can not know what link it will be eg for route {a}-0 / 0-{b} / {a}-{b} , if you ignore a then click a link with b=1 then link maybe /0-1 or 22-1 or {any}-1 so no one will ignore any of them
Further technical details
- ASP.NET Core version: 3.1.4