如何通过正则表达式从调用URL中获取路径段包括正斜杠? -ASP.NET Core

问题描述

编辑: 我需要重新打开我的问题,因为它不是RegEx问题!问题出在正斜杠上。即使RegEx匹配,我在控制器操作中也无法获得理想的结果。如果路径段包含正斜杠,则ASP.NET Core不会映射路径段。我正在寻找一种中间件,路由选项(无论是否存在)方面的解决方法

我正在寻找一种解决方案,可以从控制器动作中的调用URL中获取多个路径段,包括通过RegEx约束进行正斜杠。

示例:

用户致电:PUT api/v1/model/elements/elementCollection1/subElement1/subSubElement2/value

现在elements//value间的所有内容都应通过类似...的函数传递给名为elementPath的动作参数。

[HttpPut("api/v1/model/elements/{elementPath}/value")]
public IActionResult PutElementValue(string elementPath,[FromBody] Value value)
{
    //Here is code
}

您是否知道如何RegEx并将tge匹配映射到elementPath参数(包括正斜杠)?像这样:

[HttpPut("api/v1/model/elements/{elementPath:regex(<Here shall be the right RegEx>)}/value")]

值得注意的是,我也尝试使用*包罗万象的参数,虽然有点不合常规,但它工作了片刻。问题是我在api / v1 / model / elements / {elementPath}上有另一个Put-Operation,没有附录“ / value”。因此,我不得不正确地获取elementPath。另外,我想从Controller自动生成一个Swagger Doc,并且其中的所有内容和hack都不会被解析。

请帮助我,这是我对StackOverflow的第一个问题。

解决方法

来自docs

您可以使用星号(*)或双星号(**)作为路由参数的前缀,以绑定到URI的其余部分。这些称为全部参数。例如,blog / {** slug}匹配以/ blog开头且后跟任何值的所有URI,该URI被分配给slug路由值。 Catch-all参数也可以匹配空字符串。

当 route用于生成URL,包括路径分隔符(/) 字符。例如,路由foo / {* path}的路由值为{ path =“ my / path”}生成foo / my%2Fpath。注意向前逃跑 削减。要往返路径分隔符,请使用** route 参数前缀。路径foo / {** path}和{path =“ my / path”} 生成foo / my / path。

按如下所示更改代码:

[HttpPut("api/v1/model/elements/{**value}")]
public void PutElementValue(string value,[FromBody] string data)
{
    value = value.Replace("/value","");
}

结果: enter image description here

,

我找到了另一个解决方案,即使用URL编码的元素路径创建并注册自己的中间件。克服了不将正斜杠映射到任何路由模板的问题。

解决方案:

app.Use((context,next) =>
            {
                string requestPath = context.Request.Path.ToUriComponent();
                
                if (requestPath.Contains("elements/"))
                {
                    Match valueMatch = Regex.Match(requestPath,"(?<=elements/)(.*)(?=/value|/invoke)");
                    if(valueMatch.Success)
                    {
                        string elementPath = HttpUtility.UrlEncode(valueMatch.Value);
                        requestPath = requestPath.Replace(valueMatch.Value,elementPath);
                        context.Request.Path = new PathString(requestPath);
                    }
                    else
                    {
                        Match baseMatch = Regex.Match(requestPath,"(?<=elements/)(.*)");
                        if(baseMatch.Success)
                        {
                            string elementPath = HttpUtility.UrlEncode(baseMatch.Value);
                            requestPath = requestPath.Replace(baseMatch.Value,elementPath);
                            context.Request.Path = new PathString(requestPath);
                        }
                    }
                }
                return next();
            });

它可以工作,但仍然感觉很平庸。如果您有任何想法如何在其他方法中执行此操作-仍推荐使用Action-Route-Template中的RegEx-请让我知道;-)