Search code examples
c#.netasp.net-mvcurl-routingasp.net-mvc-routing

C# Asp.Net MVC - Parameter Only Action Request


I have an Asp.Net MVC project whereby we allow our users to have public profiles.

I would like to improve the url, so that it is more friendly, and shorter.

The existing code is as follows -

public class ProfileController : Controller
    {
        private readonly IUserProfileService _userProfileService;

        public ProfileController(IUserProfileService userProfileService)
        {
            this._userProfileService = userProfileService;
        }

        public ActionResult Index(string id)
        {
            //Get users profile from the database using the id
            var viewModel = _userProfileService.Get(id);

            return View(viewModel);
        }
    }


public class RouteConfig
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        //Required for the route prefix attributes to work!
        routes.MapMvcAttributeRoutes();

        routes.MapRoute(
            "ProfileUrlIndexActionRemoval",
            "Profile/{id}",
            new { controller = "Profile", action = "Index" }
        );

        routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
        );
    }
}

The aforementioned code allows the following url to work (based on the default MVC routing) - www.mydomain.com/profile/john-doe

What routing do I need to implement, in order to allow the following url to work instead - www.mydomain.com/john-doe

Thanks.


Solution

  • This is a little tricky as you want the friendly URL in the root of the site while not conflicting with any other routes.

    That would mean that if you have any other routes like About or Contact you would need to make sure that are in the route table before the friendly route to avoid route conflicts.

    public class RouteConfig
    {
        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    
            //Required for the route prefix attributes to work!
            routes.MapMvcAttributeRoutes();
    
            routes.MapRoute(
                "ProfileUrlIndexActionRemoval",
                "Profile/{id}",
                new { controller = "Profile", action = "Index" }
            );
    
            routes.MapRoute(
                name: "Home",
                url: "Home/{action}/{id}",
                defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
            );
    
            routes.MapRoute(
                name: "About",
                url: "About/{action}/{id}",
                defaults: new { controller = "About", action = "Index", id = UrlParameter.Optional }
            );
    
            routes.MapRoute(
                name: "Contact",
                url: "Contact/{action}/{id}",
                defaults: new { controller = "Contact", action = "Index", id = UrlParameter.Optional }
            );
    
            routes.MapRoute(
                "Default_Frieldly",
                "{*id}",
                new { controller = "Profile", action = "Index" }
            );
        }
    }
    

    And finally because the default route will capture all unmatched routes, you will need to take not found profiles into account.

    public class ProfileController : Controller {
    
        //...code removed for brevity
    
        public ActionResult Index(string id) {
            //Get users profile from the database using the id
            var viewModel = _userProfileService.Get(id);
    
            if(viewModel == null) {
                return NotFound();
            }
    
            return View(viewModel);
        }
    }
    

    By having the profile controller prefix in the original URL it made it unique so as to avoid route conflicts, but in wanting the root friendly URL, while not impossible, you see the hoops needed to jump through in order to get the desired behavior.