Warm tip: This article is reproduced from serverfault.com, please click

Url.Action not outputting custom mapped controller route

发布于 2021-10-20 18:28:34

This is for a .NET 5.0 MVC web application.

I have a controller to manage types of agencies in the Admin area of my site:

[Area("Admin")]
public class AgencyTypesController : Controller
{        
    public async Task<IActionResult> Index()
    {
        ...
    }
    
    public async Task<IActionResult> Create()
    {
        ...
    }
    
    public async Task<IActionResult> Edit(Guid id)
    {
        ...
    }        
}

The current url is at /Admin/AgencyTypes, but I would like it to be /Admin/Agencies/Types, so I have this in my Startup:

app.UseEndpoints(endpoints =>
{
    endpoints.MapControllerRoute(
        name: "areas",
        pattern: "{area:exists}/{controller=Home}/{action=Index}/{id?}"
    );
});

app.UseEndpoints(endpoints =>
{
    endpoints.MapControllerRoute(
        name: "agencytypes",
        pattern: "{area:exists}/Agencies/Types/{action=Index}",
        defaults: new { controller = "AgencyTypes", action = "Index" }
    );
});

app.UseEndpoints(endpoints =>
{
    endpoints.MapControllerRoute(
        name: "default",
        pattern: "{controller=Home}/{action=Index}/{id?}");
});

When I navigate to /Admin/Agencies/Types, it seems my routing has worked correctly, it hits the Index action in AgencyTypesController.

The problem is that my page has links to the Create and Edit methods, using Url.Action

@Url.Action("Create", "AgencyTypes", new { Area = "Admin" })
@Url.Action("Edit", "AgencyTypes", new { Area = "Admin", id = ID })

And rather than these urls being rendered as /Admin/Agencies/Types/Create and /Admin/Agencies/Types/Edit/id, it's still using the urls at /Admin/AgencyTypes/Create and /Admin/AgencyTypes/Edit

Is there something else I need to do to get Url.Action working with my custom route? Or is there something wrong with how I'm mapping my route?

Questioner
Steven
Viewed
0
Ali Zeinali 2021-10-22 04:36:14

Add more specific route first:

app.UseEndpoints(endpoints =>
{
    endpoints.MapControllerRoute(
        name: "agencytypes",
        pattern: "{area:exists}/Agencies/Types/{action=Index}",
        defaults: new { controller = "AgencyTypes", action = "Index" }
    );
});

app.UseEndpoints(endpoints =>
{
    endpoints.MapControllerRoute(
        name: "areas",
        pattern: "{area:exists}/{controller=Home}/{action=Index}/{id?}"
    );
});

app.UseEndpoints(endpoints =>
{
    endpoints.MapControllerRoute(
        name: "default",
        pattern: "{controller=Home}/{action=Index}/{id?}");
});

this is because when it gonna create a url it go through your routes which you defined and find the first one that match.

So when you add a general pattern like this {area:exists}/{controller=Home}/{action=Index}/{id?} first, it will be at the first of the list and so it always would be first pattern which match