.NET Core(2.1)Web API控制器接受请求URL中的所有后续内容作为参数

时间:2018-07-31 13:51:47

标签: c# .net-core asp.net-core-routing .net-core-2.1

我所拥有的是一个.NET Core 2.1 Web API控制器(在下面的TestController中),当接收到GET请求时,该控制器应该生成到其他URL的重定向。

示例:

控制器的名称类似于:http://localhost/api/v1/Test/somedir/somesubdir/filename.extension

,它应该返回重定向到https://example-domain.com/somedir/somesubdir/filename.extension

我针对此问题的示例控制器如下:

  [Authorize]
  [Route("api/v1/[controller]")]
  public class TestController : ControllerBase
  {
    [HttpGet("{path}")]
    public async Task<IActionResult> Get(string path)
    {
      //path e.g. is somedir/somesubdir/filename.extension
      string prefix = "https://example-domain.com/api/v1/Other/";
      //string path2 = HttpContext.Request.Path.Value.Replace("/api/v1/Test/", "/api/v1/Other/").Replace("%2F", "/");
      return Redirect(prefix + path);
    }
  }

我没有路由上班。如果我用Swagger调用该方法,则会被调用(用%2F代替斜杠),但至少会被调用。 如果我通过邮递员调用控制器,.NET Core只会返回404 Not Found。

我不一定需要HttpGet(“ {path}”)。我知道我可以像分配path2变量一样获得路径。

有没有提示我如何正确进行路由?


另一种可能的解决方案:

正如John和Kirk Larkin在评论中所指出的那样,我要寻找的是一条通吃的路线,在路径参数中填充“ somedir / somesubdir / filename.extension”,与之后的路径有多长。

在变量名前面加一个星号就可以解决问题。

[HttpGet(“ {* path}”)]

3 个答案:

答案 0 :(得分:4)

您无需考虑代码注释所建议的"api/v1/Test",它已经被Controller级别的[Route]属性过滤掉了。

对于随后的其余路径,您可以使用 {*path}

[HttpGet("{*path}")]
public async Task<IActionResult> Get(string path)
{
    const string prefix = "https://example-domain.com/api/v1/Other/";
    return Redirect(prefix + path);
}

答案 1 :(得分:2)

@john,他的解决方案很棒:[HttpGet("{*path}")],刚刚经过测试。但我想保留使用功能的答案作为选择:

作为另一种选择,您可以遵循MSDN [全包路由]:https://docs.microsoft.com/en-us/aspnet/core/fundamentals/routing?view=aspnetcore-2.1

routes.MapRoute(
  name: "blog",
  template: "Blog/{*article}", //<==
  defaults: new { controller = "Blog", action = "ReadArticle" });
  

此模板将与以下网址路径匹配   / Blog / All-About-Routing / Introduction,并将提取值{   控制器=博客,操作= ReadArticle,文章=   全面路由/简介}。的默认路由值   控制器和动作是由路线产生的,即使有   模板中没有相应的路由参数。默认值可以   在路由模板中指定。文章路径参数为   通过星号*的出现定义为全部   路由参数名称。捕获所有路由参数,捕获其余部分   网址路径,也可以匹配空字符串。

最后一个选择是:不要使用控制器,而是在全局配置中使用它:

public class Startup
{
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        app.Map("api/v1/Test", x =>
        {
            x.Run(async context =>
            {
                //path e.g. is somedir/somesubdir/filename.extension
                string prefix = "https://example-domain.com/api/v1/Other/";
                string path = context.Request.Path.Value.Replace("/api/v1/Test/", "/api/v1/Other/").Replace("%2F", "/");
                context.Response.Redirect(prefix + path);
            });
        });
    }
}

答案 2 :(得分:0)

我认为您需要像接收URL一样接收这3个参数,所以..该方法应该是这样的...

[Route("{dir}/{subdir}/filename")]
public async Task<IActionResult> Get(string dir, string subdir, string filename)
{
  string path = dir + "/" + subdir + "/" + filename;
  //path e.g. is somedir/somesubdir/filename.extension
  string prefix = "https://example-domain.com/api/v1/Other/";
  //string path2 = HttpContext.Request.Path.Value.Replace("/api/v1/Test/", "/api/v1/Other/").Replace("%2F", "/");
  return Redirect(prefix + path);
}