忽略ASP.NET MVC Core路由中的第一部分 [英] Ignore first segments in ASP.NET MVC Core routing

查看:115
本文介绍了忽略ASP.NET MVC Core路由中的第一部分的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找一个能够匹配以下路线的路线定义:

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路由中的第一部分的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆