1

我不确定我应该如何命名我的视图页面,它们都是 CamelCase.cshtml,在浏览器中查看时看起来像“ http://www.website.com/Home/CamelCase ”。

当我在 .NET 之外构建时,我的页面被命名为“this-is-not-camel-case.html”。我将如何在我的 MVC4 项目中执行此操作?

如果我确实这样做了,那么我将如何告诉视图查看相关的控制器?Views/Home/camel-case.cshtml

虚假编辑:抱歉,如果之前有人问过这个问题,我无法通过搜索或 Google 找到任何内容。谢谢。

4

1 回答 1

2

有几种方法可以做到这一点:

以您希望它们在 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;
        }
    }
}
于 2013-05-24T16:50:27.170 回答