Search code examples
c#routesactionlinkhtml.actionlinkcustom-routes

C# Custom Map Routes / View Paths / Link Generation


Issue/Try 1:
I have a custom route map:

routes.MapRoute(
    name: "User Profile",
    url: "User/{userId}/{controller}/{action}/{id}",
    defaults: new { Areas = "User", controller = "Kpi", action = "Index", id = UrlParameter.Optional }
);

If i manually navigate to the URL /User/f339e768-fe92-4322-93ca-083c3d89328c/Kpi/View/1 the page loads with a View Error: The view 'View' or its master was not found or no view engine supports the searched locations.

Issue/Try 2:
Stopped using the custom route and set up my controller as instead:

    [RouteArea("User")]
    [RoutePrefix("{userId}/Kpi")]
    public class KpiController : BaseUserController
    {
        [Route("View/{id}")]
        public async Task<ActionResult> View(string userId, int? id = null)
        {
            [...]
        }
    }

This now works i can navigate to the URL and the View displays fine.

Issue for both:
Although I can navigate manually to both and they load I can't seem to generate the URL correctly using ActionLink:

@Html.ActionLink(kpi.GetFormattedId(), "View", "Kpi", new { Area = "User", userId = Model.Id, id = kpi.Id }, null)

It generates: /User/Kpi/View/1?userId=f339e768-fe92-4322-93ca-083c3d89328c instead of /User/f339e768-fe92-4322-93ca-083c3d89328c/Kpi/View/1


Solution

  • URL Mapping
    After some time i have found the solution for the custom mapping i was adding in the main RouteConfig.cs and not in the Area Registration. Moving the MapRoute to the Area works correctly and without the RouteArea, RoutePrefix and Route attributes in the Controller.

    Area Registration

    public class UserAreaRegistration : AreaRegistration 
    {
        public override string AreaName => "User";
    
        public override void RegisterArea(AreaRegistrationContext context)
        {
            context.MapRoute(
                name: "User",
                url: "User/{userId}/{controller}/{action}/{id}",
                defaults: new { action = "Index", id = UrlParameter.Optional }
            );
    
            context.MapRoute(
                "User_default",
                "User/{controller}/{action}/{id}",
                new {action = "Index", id = UrlParameter.Optional}
            );
        }
    }
    

    Links
    Instead of using ActionLink i am now using RouteLink.

    @Html.RouteLink("KPIs", "User", new { Controller = "Kpi", Action = "Index", userId = Model.Id })