Url generate problem
- Dominant language
- C#
- Stars
- 38.4k
- Forks
- 10.9k
- Avg merge
- 2d 10h
- Merged PRs (30d)
- 281
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 https://github.com/aspnet/Mvc/issues/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:
```C#
// [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**
```razor
this link is wrong
```
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
```razor
the view must know your controller add a `b` route variable
```
### To Reproduce
https://github.com/John0King/UrlGenTest it's the old repo , but it explain everything
### what cause it
1. 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/getlist` instead of generate it )
2. **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
Contributor guide
Assessment
This issue has not been assessed yet.