I couldn't find an answer to this that covered all issues one would face with a public facing website without being a pain to upkeep while still maintaining flexibility.
I ended up coming up with the following. It allows for use of multiple controllers, doesn't require any upkeep, and makes all URLs lowercase.
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
//set up constraints automatically using reflection - shouldn't be an issue as it only runs on appstart
var homeConstraints = @"^(?:" + string.Join("|", (typeof(Controllers.HomeController)).GetMethods(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.DeclaredOnly).Select(x => (x.Name == "Index" ? "" : x.Name))) + @")$";
//makes all urls lowercase, which is preferable for a public facing website
routes.LowercaseUrls = true;
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
//maps routes with a single action to only those methods specified within the home controller thanks to contraints
routes.MapRoute(
"HomeController",
"{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new { action = homeConstraints }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}