我正在寻找一个能够匹配以下路线的路线定义:
I'm looking for a route definition that is able to match routes like:
- / segment / xxxx / def
- / segment /.../ xxxx / def
- / segment / that / can / span / xxxx / def
- /segment/xxxx/def
- /segment/.../xxxx/def
- /segment/that/can/span/xxxx/def
并能够使用参数`def运行 xxxx 动作。
and be able to run the action xxxx with param `def.
不允许:
[Route("/{*segment}/xxx/{myparam}")]如何完成?
推荐答案您可以将自定义 IRouter 与正则表达式结合使用来进行高级URL匹配,例如。
You can use a custom IRouter combined with a regular expression to do advanced URL matching such as this.
public class EndsWithRoute : IRouter { private readonly Regex urlPattern; private readonly string controllerName; private readonly string actionName; private readonly string parameterName; private readonly IRouter handler; public EndsWithRoute(string controllerName, string actionName, string parameterName, IRouter handler) { if (string.IsNullOrWhiteSpace(controllerName)) throw new ArgumentException($"'{nameof(controllerName)}' is required."); if (string.IsNullOrWhiteSpace(actionName)) throw new ArgumentException($"'{nameof(actionName)}' is required."); if (string.IsNullOrWhiteSpace(parameterName)) throw new ArgumentException($"'{nameof(parameterName)}' is required."); this.controllerName = controllerName; this.actionName = actionName; this.parameterName = parameterName; this.handler = handler ?? throw new ArgumentNullException(nameof(handler)); this.urlPattern = new Regex($"{actionName}/[^/]+/?$", RegexOptions.Compiled | RegexOptions.IgnoreCase); } public VirtualPathData GetVirtualPath(VirtualPathContext context) { var controller = context.Values.GetValueOrDefault("controller") as string; var action = context.Values.GetValueOrDefault("action") as string; var param = context.Values.GetValueOrDefault(parameterName) as string; if (controller == controllerName && action == actionName && !string.IsNullOrEmpty(param)) { return new VirtualPathData(this, $"{actionName}/{param}".ToLowerInvariant()); } return null; } public async Task RouteAsync(RouteContext context) { var path = context.HttpContext.Request.Path.ToString(); // Check if the URL pattern matches if (!urlPattern.IsMatch(path, 1)) return; // Get the value of the last segment var param = path.Split('/').Last(); //Invoke MVC controller/action var routeData = context.RouteData; routeData.Values["controller"] = controllerName; routeData.Values["action"] = actionName; // Putting the myParam value into route values makes it // available to the model binder and to action method parameters. routeData.Values[parameterName] = param; await handler.RouteAsync(context); } }用法
Usage
app.UseMvc(routes => { routes.Routes.Add(new EndsWithRoute( controllerName: "Home", actionName: "About", parameterName: "myParam", handler: routes.DefaultHandler)); routes.MapRoute( name: "default", template: "{controller=Home}/{action=Index}/{id?}"); });此路由已参数化,以允许您传入与之对应的控制器,操作和参数名称
This route is parameterized to allow you to pass in the controller, action, and parameter names that correspond to the action method being called.
public class HomeController : Controller { public IActionResult About(string myParam) { ViewData["Message"] = "Your application description page."; return View(); } }要使其与 any 操作方法名称,并能够使用该操作方法名称再次构建URL。但这条路线将使您可以通过多次注册来添加其他操作名称。
It would take some more work to make it match any action method name and be able to build the URL again with that action method name. But this route will allow you to add additional action names by registering it more than one time.
注意:出于SEO的目的,通常不建议将相同的内容放在多个URL上。如果这样做,建议使用规范标记来告知搜索引擎哪个URL是权威一个。
NOTE: For SEO purposes, it is generally not considered a good practice to put the same content on multiple URLs. If you do this, it is recommended to use a canonical tag to inform the search engines which of the URLs is the authoritative one.
在ASP.NET MVC(ASP.NET Core之前的版本)中,请参见此处实现相同的操作。
更多推荐
忽略ASP.NET MVC Core路由中的第一部分
发布评论