在.NET MVC 4.0 URL结构中强制使用连字符

时间:2011-12-11 10:36:51

标签: asp.net-mvc-routing lowercase hyphenation asp.net-mvc-4

我正在寻找一种自动连接CamelCase操作和视图的方法。也就是说,我希望我不必实际重命名我的视图或向网站中的每个ActionResult添加装饰器。

到目前为止,我一直在使用routes.MapRouteLowercase,如图所示here。这对于URL结构的小写方面非常有效,但不适用于连字符。所以我最近开始玩Canonicalize(通过NuGet安装),但它也没有任何连字符。

我在努力......

routes.Canonicalize().NoWww().Pattern("([a-z0-9])([A-Z])", "$1-$2").Lowercase().NoTrailingSlash();

我的正则表达式肯定会按照我希望的方式正常工作,正确地重构URL,但当然不会识别这些URL。例如,该文件仍为ChangePassword.cshtml,因此/account/change-password不会指向该文件。

顺便说一句,我对.NET MVC仍然有点生疏。我没有使用它几年,而不是从v2.0开始。

4 个答案:

答案 0 :(得分:3)

这可能有点混乱,但如果您创建了自定义HttpHandlerRouteHandler,则应该可以防止您重命名所有视图和操作。您的处理程序可以从请求的操作中删除连字符,这会将“change-password”更改为changepassword,从而呈现ChangePassword操作。

为简洁起见,代码缩短了,但重要的部分就在那里。

public void ProcessRequest(HttpContext context)
{
    string controllerId = this.requestContext.RouteData.GetRequiredString("controller");
    string view = this.requestContext.RouteData.GetRequiredString("action");

    view = view.Replace("-", "");
    this.requestContext.RouteData.Values["action"] = view;

    IController controller = null;
    IControllerFactory factory = null;

    try
    {
        factory = ControllerBuilder.Current.GetControllerFactory();
        controller = factory.CreateController(this.requestContext, controllerId);

        if (controller != null)
        {
            controller.Execute(this.requestContext);
        }
    }
    finally
    {
        factory.ReleaseController(controller);
    }
}

我不知道我是否以最佳方式实施,这或多或少取自我遇到的第一个sample。我自己测试了代码,所以这确实呈现了正确的操作/视图,并应该做到这一点。

答案 1 :(得分:3)

我为此问题开发了一个开源 NuGet库,它隐式地将EveryMvc / Url转换为每个mvc / url。

大写网址存在问题,因为Cookie路径区分大小写,大多数互联网实际上区分大小写,而Microsoft技术将网址视为不区分大小写。 (More on my blog post

NuGet套餐:https://www.nuget.org/packages/LowercaseDashedRoute/

要安装它,只需在Visual Studio中打开NuGet窗口,右键单击Project并选择NuGet Package Manager,然后在“Online”选项卡上键入“Lowercase Dashed Route”,它就会弹出。

或者,您可以在程序包管理器控制台中运行此代码

Install-Package LowercaseDashedRoute

之后你应该打开App_Start / RouteConfig.cs并注释掉现有的route.MapRoute(...)调用并添加它:

routes.Add(new LowercaseDashedRoute("{controller}/{action}/{id}",
  new RouteValueDictionary(
    new { controller = "Home", action = "Index", id = UrlParameter.Optional }),
    new DashedRouteHandler()
  )
);

就是这样。所有网址都是小写,虚线和隐式转换,而不需要你做更多的事情。

开源项目网址:https://github.com/AtaS/lowercase-dashed-route

答案 2 :(得分:0)

您是否尝试过使用URL Rewrite包?我认为这几乎就是你要找的东西。

http://www.iis.net/download/urlrewrite

Hanselman有一个很好的例子:

http://www.hanselman.com/blog/ASPNETMVCAndTheNewIIS7RewriteModule.aspx

此外,为什么不下载ReSharper或CodeRush等内容,并使用它来重构Action和Route名称? 非常简单,非常安全。

使用一小时的重构来修复路由/操作命名约定的总时间要比花费在尝试根据需要更改路由约定的所有时间而花费更少的时间。

只是一个想法。

答案 3 :(得分:0)

我在上面接受的答案中尝试了解决方案:使用Canonicalize Pattern网址策略,然后添加自定义IRouteHandler,然后返回自定义IHttpHandler。它主要是工作。以下是我发现的一个警告:

使用典型的{controller}/{action}/{id}默认路由,名为CatalogController的控制器及其中的操作方法如下:

ActionResult QuickSelect(string id){ /*do some things, access the 'id' parameter*/ }

我注意到对“/ catalog / quick-select / 1234”的请求工作得很好,但对/ catalog / quick-select?id = 1234的请求是500'ing,因为一旦action方法被调用{ {1}},controller.Execute()参数在操作方法中为null。

我不确切知道为什么会这样,但行为就好像MVC在模型绑定期间没有查看值的查询字符串。所以在接受的答案中关于id实现的一些事情搞砸了正常的模型绑定过程,或者至少是查询字符串值提供者。

这是一个交易破坏者,所以我看了默认的MVC IHttpHandler(耶和开源!):http://aspnetwebstack.codeplex.com/SourceControl/latest#src/System.Web.Mvc/MvcHandler.cs

我不会假装我完整地理解它,但很明显,它在ProcessRequest的实施中所做的比在接受的答案中所做的更多。

所以,如果我们真正需要做的就是从我们的传入路由数据中删除破折号,以便MVC可以找到我们的控制器/动作,为什么我们需要实现一个完整的臭味IHttpHandler?我们不!只需在ProcessRequest的{​​{1}}方法中删除短划线,然后将GetHttpHandler传递给开箱即用DashedRouteHandler,这样就可以完成252行魔法,并且你的路由处理程序不必返回第二个速率IHttpHandler。

<强> TL:博士; - 这就是我的所作所为:

requestContext