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

查看:24
本文介绍了忽略 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

并且能够运行带有参数`def.

and be able to run the action xxxx with param `def.

但是这种路线是不允许的:

But this kind of route isn't allowed:

[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);
    }
}

用法

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();
    }
}

要使其匹配任何操作方法名称,并能够使用该操作方法名称再次构建 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 上不是一个好习惯.如果您这样做,建议使用规范标签通知搜索引擎哪个网址是权威网址.

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天全站免登陆