.NET Core (2.1) web API controller accepting all that follows within the request url as parameter
.NET Core (2.1) web API controller accepting all that follows within the request url as parameter
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?
{*path}
@john post your comment as answer and I will accept it, it worked exactly like that HttpGet("{*path}")
– monty
5 mins ago
It's called a catch-all route, if that helps.
– Kirk Larkin
4 mins ago
3 Answers
3
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.
"api/v1/Test"
For the rest of the path that follows you can use {*path}
:
{*path}
[HttpGet("{*path}")]
public async Task<IActionResult> Get(string path)
{
const string prefix = "https://example-domain.com/api/v1/Other/";
return Redirect(prefix + path);
}
@john, his solution is wonderful: [HttpGet("{*path}")]
, just tested. but I want to keep my answer for feature use as an option:
[HttpGet("{*path}")]
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);
});
});
}
}
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);
}
Unfortunatly I can't do it that way since I do not know the incoming structure of path. It could be somedir/somesubdir/file.png or 15 subdirs before the filename
– monty
17 mins ago
Then you need to receive all the path in one parameter, and encode the path segment of the url the same way Swagger is doing
– Nicolás Loaiza
11 mins ago
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
Don't quote me on this :) but I swear you could do something like
{*path}
.– john
22 mins ago