.NET Core (2.1) web API controller accepting all that follows within the request url as parameter

孤人 提交于 2019-12-11 09:02:08

问题


What I have is a .NET Core 2.1 web API controller (in the following the TestController) that should generate redirects to other urls when receiving GET requests.

Example:

The controller is called like: http://localhost/api/v1/Test/somedir/somesubdir/filename.extension

and it should return a redirect to https://example-domain.com/somedir/somesubdir/filename.extension

My example controller for this question looks like:

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

I don't get the routing to work. If I call the method with Swagger it get's called (with the slashes replaced by %2F) but at least it gets called. If I call the controller via postman .NET Core just returns 404 Not Found.

I do not necessarily need the HttpGet("{path}"). I know that I could get the path like I assigned the path2 variable.

Any hints how I could get the routing right?


Another possible solution:

As pointed out by John and Kirk Larkin in the comments what I was looking for is a catch-all route filling the path argument with "somedir/somesubdir/filename.extension" independent how long the path afterwards is.

Just an asterisk in front of the variable name does the trick.

[HttpGet("{*path}")]


回答1:


You don't need to take "api/v1/Test" into account as your code comments suggest, it is already filtered out by the [Route] attribute on the Controller level.

For the rest of the path that follows you can use {*path}:

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



回答2:


@john, his solution is wonderful: [HttpGet("{*path}")], just tested. but I want to keep my answer for feature use as an option:

as another option, you can follow MSDN [Catch-all route]: 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" });

This template will match a URL path like /Blog/All-About-Routing/Introduction and will extract the values { controller = Blog, action = ReadArticle, article = All-About-Routing/Introduction }. The default route values for controller and action are produced by the route even though there are no corresponding route parameters in the template. Default values can be specified in the route template. The article route parameter is defined as a catch-all by the appearance of an asterisk * before the route parameter name. Catch-all route parameters capture the remainder of the URL path, and can also match the empty string.

last options is: don't use controller, and do it in global configure:

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



回答3:


I think you need to receive those 3 params separated as you have in your URL, so.. that method should be something like this...

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


来源:https://stackoverflow.com/questions/51615005/net-core-2-1-web-api-controller-accepting-all-that-follows-within-the-request

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!