在 .NET MVC 4.0 URL 结构中强制使用连字符
我正在专门寻找一种自动连接 CamelCase 操作和视图的方法。也就是说,我希望不必实际重命名我的视图或向站点中的每个 ActionResult 添加装饰器。
到目前为止,我一直在使用 routes.MapRouteLowercase
,如图 这里。这对于 URL 结构的小写部分非常有效,但对于连字符则不然。所以我最近开始使用 Canonicalize (通过 NuGet 安装),但它也没有任何连字符然而。
我正在尝试...
routes.Canonicalize().NoWww().Pattern("([a-z0-9])([AZ])", "$1-$2").Lowercase().NoTrailingSlash ();
我的正则表达式肯定按照我想要的方式工作,只要正确地重构 URL,但这些 URL 当然不会被识别。例如,该文件仍然是 ChangePassword.cshtml
,因此 /account/change-password
不会指向该文件。
顺便说一句,我对 .NET MVC 还是有点生疏。我已经好几年没有使用它了,而且从 v2.0 开始就没有使用过它。
I'm looking specifically for a way to automatically hyphenate CamelCase actions and views. That is, I'm hoping I don't have to actually rename my views or add decorators to every ActionResult in the site.
So far, I've been using routes.MapRouteLowercase
, as shown here. That works pretty well for the lowercase aspect of URL structure, but not hyphens. So I recently started playing with Canonicalize (install via NuGet), but it also doesn't have anything for hyphens yet.
I was trying...
routes.Canonicalize().NoWww().Pattern("([a-z0-9])([A-Z])", "$1-$2").Lowercase().NoTrailingSlash();
My regular expression definitely works the way I want it to as far as restructuring the URL properly, but those URLs aren't identified, of course. The file is still ChangePassword.cshtml
, for example, so /account/change-password
isn't going to point to that.
BTW, I'm still a bit rusty with .NET MVC. I haven't used it for a couple years and not since v2.0.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
这可能有点混乱,但是如果您创建了自定义 HttpHandler 和 RouteHandler 那么应该防止您不必重新命名您所有的观点和行为。您的处理程序可以从请求的操作中删除连字符,这会将“change-password”更改为changepassword,从而呈现ChangePassword操作。
为了简洁起见,代码被缩短了,但重要的部分仍然存在。
我不知道我是否以最好的方式实现了它,这或多或少是从第一个 示例 我遇到的。我自己测试了代码,因此这确实呈现了正确的操作/视图并且应该可以解决问题。
This might be a tad bit messy, but if you created a custom HttpHandler and RouteHandler then that should prevent you from having to rename all of your views and actions. Your handler could strip the hyphen from the requested action, which would change "change-password" to changepassword, rendering the ChangePassword action.
The code is shortened for brevity, but the important bits are there.
I don't know if I implemented it the best way or not, that's just more or less taken from the first sample I came across. I tested the code myself so this does render the correct action/view and should do the trick.
我针对这个问题开发了一个开源 NuGet 库,它隐式地将 EveryMvc/Url 转换为 every-mvc/url。
大写 url 是有问题的,因为 cookie 路径区分大小写,大多数互联网实际上是区分大小写的,而 Microsoft 技术将 url 视为不区分大小写。 (更多内容请参阅我的博客文章)
NuGet 包:https://www.nuget.org/packages/LowercaseDashedRoute/
要安装它,只需在 Visual Studio 中打开 NuGet 窗口即可右键单击项目并选择 NuGet Package Manager,然后在“Online”选项卡上键入“Lowercase Dashed Route”,它应该会弹出。
或者,您可以在包管理器控制台中运行此代码:
Install-Package LowercaseDashedRoute
之后,您应该打开 App_Start/RouteConfig.cs 并注释掉现有的route.MapRoute(。 ..) 调用并添加以下内容:
就是这样。所有 url 均为小写、虚线,并且隐式转换,无需您执行任何其他操作。
开源项目网址:https://github.com/AtaS/lowercase-dashed-route
I've developed an open source NuGet library for this problem which implicitly converts EveryMvc/Url to every-mvc/url.
Uppercase urls are problematic because cookie paths are case-sensitive, most of the internet is actually case-sensitive while Microsoft technologies treats urls as case-insensitive. (More on my blog post)
NuGet Package: https://www.nuget.org/packages/LowercaseDashedRoute/
To install it, simply open the NuGet window in the Visual Studio by right clicking the Project and selecting NuGet Package Manager, and on the "Online" tab type "Lowercase Dashed Route", and it should pop up.
Alternatively, you can run this code in the Package Manager Console:
Install-Package LowercaseDashedRoute
After that you should open App_Start/RouteConfig.cs and comment out existing route.MapRoute(...) call and add this instead:
That's it. All the urls are lowercase, dashed, and converted implicitly without you doing anything more.
Open Source Project Url: https://github.com/AtaS/lowercase-dashed-route
您是否尝试过使用 URL 重写包?我认为这正是您正在寻找的。
http://www.iis.net/download/urlrewrite
Hanselman 有一个很好的例子E:
< a href="http://www.hanselman.com/blog/ASPNETMVCAndTheNewIIS7RewriteModule.aspx" rel="nofollow">http://www.hanselman.com/blog/ASPNETMVCAndTheNewIIS7RewriteModule.aspx
此外为什么不下载像 ReSharper 或 CodeRush 这样的东西,并用它来重构操作和路由名称?这真的很简单,而且非常安全。
通过一个小时的重构来修复路由/操作命名约定的时间会比您已经花费在尝试根据需要更改路由约定的所有时间要少得多。
只是一个想法。
Have you tried working with the URL Rewrite package? I think it pretty much what you are looking for.
http://www.iis.net/download/urlrewrite
Hanselman has a great example herE:
http://www.hanselman.com/blog/ASPNETMVCAndTheNewIIS7RewriteModule.aspx
Also, why don't you download something like ReSharper or CodeRush, and use it to refactor the Action and Route names? It's REALLY easy, and very safe.
It would time well spent, and much less time overall to fix your routing/action naming conventions with an hour of refactoring than all the hours you've already spent trying to alter the routing conventions to your needs.
Just a thought.
我尝试了上面接受的答案中的解决方案:使用 Canonicalize Pattern url 策略,然后还添加一个自定义 IRouteHandler,然后返回一个自定义 IHttpHandler。它大部分都有效。这是我发现的一个警告:
使用典型的
{controller}/{action}/{id}
默认路由、名为CatalogController
的控制器以及其中的操作方法,如下所示:我注意到对“/catalog/quick-select/1234”的请求工作得很好,但对 /catalog/quick-select?id=1234 的请求是 500'ing,因为一旦由于以下原因调用了操作方法
controller.Execute()
,action 方法内的id
参数为 null。我不知道具体原因,但行为就好像 MVC 在模型绑定期间没有查看查询字符串中的值。因此,接受的答案中有关 ProcessRequest 实现的某些内容搞砸了正常的模型绑定过程,或者至少搞砸了查询字符串值提供程序。
这是一个大问题,所以我看了一下默认的 MVC IHttpHandler(开源!): http://aspnetwebstack.codeplex.com/SourceControl/latest#src/System.Web.Mvc/MvcHandler.cs
我不会假装我完全理解了它,但显然,它在 ProcessRequest 的实现中所做的事情比接受的答案中发生的事情要多得多。
因此,如果我们真正需要做的只是从传入的路由数据中去掉破折号,以便 MVC 可以找到我们的控制器/操作,那么为什么我们需要实现整个令人讨厌的 IHttpHandler?我们不!只需去掉
DashedRouteHandler
的GetHttpHandler
方法中的破折号,然后将requestContext
传递到开箱即用的MvcHandler
因此它可以发挥 252 行的魔力,并且您的路由处理程序不必返回第二速率的 IHttpHandler。tl:博士; - 这就是我所做的:
I tried the solution in the accepted answer above: Using the Canonicalize Pattern url strategy, and then also adding a custom IRouteHandler which then returns a custom IHttpHandler. It mostly worked. Here's one caveat I found:
With the typical
{controller}/{action}/{id}
default route, a controller namedCatalogController
, and an action method inside it as follows:I noticed that requests to "/catalog/quick-select/1234" worked perfectly, but requests to /catalog/quick-select?id=1234 were 500'ing because once the action method was called as a result of
controller.Execute()
, theid
parameter was null inside of the action method.I do not know exactly why this is, but the behavior was as if MVC was not looking at the query string for values during model binding. So something about the
ProcessRequest
implementation in the accepted answer was screwing up the normal model binding process, or at least the query string value provider.This is a deal breaker, so I took a look at default MVC IHttpHandler (yay open source!): http://aspnetwebstack.codeplex.com/SourceControl/latest#src/System.Web.Mvc/MvcHandler.cs
I will not pretend that I grok'ed it in its entirety, but clearly, it's doing ALOT more in its implementation of
ProcessRequest
than what is going on in the accepted answer.So, if all we really need to do is strip dashes from our incoming route data so that MVC can find our controllers/actions, why do we need to implement a whole stinking IHttpHandler? We don't! Simply rip out the dashes in the
GetHttpHandler
method ofDashedRouteHandler
and pass therequestContext
along to the out of the boxMvcHandler
so it can do its 252 lines of magic, and your route handler doesn't have to return a second rate IHttpHandler.tl:dr; - Here's what I did: