原文地址:Defining Routes using Regular Expressions in ASP.NET MVC
貌似是很老很老的帖子,最近要用正则弄路由,顺手翻了。
把玩一阵ASP.NET MVC Framework beta2之后,我对路由功能感觉比较失望。现在是用一个请求字符串设置一条路由信息, 映射为Controller, Action, 以及Action所需要的参数。在大多数情况下工作起来没有问题,但是在比较复杂的情况下让人比较郁闷。
Scott Guthrie曾经在他的帖子中回答了他们为什么不使用正则表达式来定义路由信息,声称因为大多数人不会用,不过他承诺以后可能会作为一个备选方案,但是既然我们可以实现的话,为啥要等呢?这是我的RegexRoute类,很快很丑陋:
public class RegexRoute : Route { private readonly Regex _urlRegex; public RegexRoute(string urlPattern, IRouteHandler routeHandler) : this(urlPattern, null, routeHandler) { } public RegexRoute(string urlPattern, RouteValueDictionary defaults, IRouteHandler routeHandler) : base(null, defaults, routeHandler) { _urlRegex = new Regex(urlPattern, RegexOptions.Compiled); } public override RouteData GetRouteData(HttpContextBase httpContext) { string requestUrl = httpContext.Request.AppRelativeCurrentExecutionFilePath.Substring(2) + httpContext.Request.PathInfo; Match match = _urlRegex.Match(requestUrl); RouteData data = null; if (match.Success) { data = new RouteData(this, RouteHandler); // add defaults first if (null != Defaults) { foreach (var def in Defaults) { data.Values[def.Key] = def.Value; } } // iterate matching groups for (int i = 1; i < match.Groups.Count; i++) { Group group = match.Groups[i]; if (group.Success) { string key = _urlRegex.GroupNameFromNumber(i); if (!String.IsNullOrEmpty(key) && !Char.IsNumber(key, 0)) // only consider named groups { data.Values[key] = group.Value; } } } } return data; } }
顺便说一下,把路由使用正则表达式的方式定义,给我们带来了很爽的“副作用”,允许我们执行验证,比如某种并不必要的约束。
routes.Add(new RegexRoute(@"^Books/((?<ssn>[\d]{3}(-?)[\d]{2}\1[\d]{4})|(?<query>.+)?)$", new MvcRouteHandler()) { Defaults = new RouteValueDictionary(new { controller = "Book", action = "Find" }) });
上面的路由把请求分隔成两部分,一部分通过ssn选择书籍,另一部分用于通过书名搜索,我想演示使用正则表达式的灵活性,上面的代码中像这样的url请求“mysite.com/Books/Last+Argument+Of+Kings”和“mysite.com/Books/0575077905”都可以用过这个路由映射信息找到相应的action:Find(),像这样定义:
public class BookController : Controller { public void Find(string query, int? ssn) { // ... gets the book by ssn if present, otherwise searches using the query } }
虽然可以使用正则,我对路由仍然不是100%满意,它不允许我重载controll action(现在的版本可以了),上面的示例中,我宁愿弄2个不同的查找方法:Find(string query)和Find(int ssn),通过路由信息分析请求之后调用不同的action,但是MvcRouteHandler却不知道怎么解决这个问题,只晓得抛异常。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 周边上新:园子的第一款马克杯温暖上架
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
· 使用C#创建一个MCP客户端