有几种方法可以做到这一点:
以您希望它们在 url 中显示的样式命名所有视图
这非常简单,您只需将ActionName属性添加到所有操作并以您希望 url 的样式指定它们,然后将 CamelCase.cshtml 文件重命名为 camel-case.cshtml 文件。
使用属性路由
与上述相同,nuget 上有一个插件可以启用属性路由,它允许您将每个操作的完整 url 指定为操作的属性。它具有约定属性来帮助您使用控制器名称等。我通常更喜欢这种方法,因为我喜欢非常明确地使用我的应用程序中的路由。
一种更加框架化的方法
通过扩展 MVC 框架可能会做一些基于约定的事情,但这将是大量的工作。为了在控制器上选择正确的操作,您需要在框架使用它来定位控制器上的操作之前,将进入 MVC 的操作名称映射到其 CamelCase 等效项。最容易做到这一点的地方是在 Route 中,这是 MVC 框架接管请求之前发生的最后一件事。您还需要在输出时转换另一种方式,以便生成的 url 看起来像您想要的那样。
由于您真的不想更改现有方法来注册路由,因此最好在 application init 中编写一个函数,该函数在注册后遍历所有路由并用您的新功能包装它们。
这是一个示例路由和对应用程序启动的修改,以实现您想要做的事情。但是,我仍然会使用路由属性方法。
public class MvcApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();
        WebApiConfig.Register(GlobalConfiguration.Configuration);
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        WrapRoutesWithNamingConvention(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);
        AuthConfig.RegisterAuth();
    }
    private void WrapRoutesWithNamingConvention(RouteCollection routes)
    {
        var wrappedRoutes = routes.Select(m => new ConventionRoute(m)).ToList();
        routes.Clear();
        wrappedRoutes.ForEach(routes.Add);
    }
    private class ConventionRoute : Route
    {
        private readonly RouteBase baseRoute;
        public ConventionRoute(RouteBase baseRoute)
            : base(null, null)
        {
            this.baseRoute = baseRoute;
        }
        public override RouteData GetRouteData(HttpContextBase httpContext)
        {
            var baseRouteData = baseRoute.GetRouteData(httpContext);
            if (baseRouteData == null) return null;
            var actionName = baseRouteData.Values["action"] as string;
            var convertedActionName = ConvertHyphensToPascalCase(actionName);
            baseRouteData.Values["action"] = convertedActionName;
            return baseRouteData;
        }
        private string ConvertHyphensToPascalCase(string hyphens)
        {
            var capitalParts = hyphens.Split('-').Select(m => m.Substring(0, 1).ToUpper() + m.Substring(1));
            var pascalCase = String.Join("", capitalParts);
            return pascalCase;
        }
        public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
        {
            var valuesClone = new RouteValueDictionary(values);
            var pascalAction = valuesClone["action"] as string;
            var hyphens = ConvertPascalCaseToHyphens(pascalAction);
            valuesClone["action"] = hyphens;
            var baseRouteVirtualPath = baseRoute.GetVirtualPath(requestContext, valuesClone);
            return baseRouteVirtualPath;
        }
        private string ConvertPascalCaseToHyphens(string pascal)
        {
            var pascalParts = new List<string>();
            var currentPart = new StringBuilder();
            foreach (var character in pascal)
            {
                if (char.IsUpper(character) && currentPart.Length > 0)
                {
                    pascalParts.Add(currentPart.ToString());
                    currentPart.Clear();
                }
                currentPart.Append(character);
            }
            if (currentPart.Length > 0)
            {
                pascalParts.Add(currentPart.ToString());
            }
            var lowers = pascalParts.Select(m => m.ToLower());
            var hyphens = String.Join("-", lowers);
            return hyphens;
        }
    }
}