问题
I want to support routes such as /route/param1
, /route/param1/param2
, /route/param1/param2/param3
and so on.
For now I have define in my Controller one route per combination of parameters:
[Route("{path1}")]
public async Task<IActionResult> Route1(string path1)
{
return await ParsePath(new[] { path1 });
}
[Route("{path1}/{path2}")]
public async Task<IActionResult> Route2(string path1, string path2)
{
return await ParsePath(new[] { path1, path2 });
}
This has 2 major drawback:
- For now I have 8 of these so I can only support up to 8 parameters
- This code is not very DRY if I want to support more parameters
I would prefer to use a method with such signature:
public async Task<IActionResult> RouteMultiple(params string[] paths)
{
return await ParsePath(queryString, paths);
}
but is this compatible with the Route
attribute?
回答1:
What about this:
[Route("{path1?}/{path2?}/{path3?}/{path4?}")]
public async Task<IActionResult> RouteMultiple(string path1, string path2, ... and so on)
{
return await ParsePath(new[] { path1, path2, ... and so on });
}
It works in Postman.
回答2:
There's no way to do this in a Controller action, because they're not thought for these situations. You can, however, go outside the MVC world and use a middleware directly on the desired path.
Where you configure:
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
add another map to your dynamic route:
app.UseEndpoints(endpoints =>
{
endpoints.Map("Products/{**values}", DynamicPathMiddleware.InvokeAsync);
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
Where DynamicPathMiddleware.InvokeAsync
is a very simple static method like this:
public class DynamicPathMiddleware
{
public static async Task InvokeAsync(HttpContext context)
{
var paths = context.Request.Path.Value.Substring("Products/".Length + 1).Split('/');
// from the question's code
await ParsePath(paths);
// and write to the response with
await context.Response.WriteAsync(JsonSerializer.Serialize(paths));
}
}
With the code above, going to /Products/asd/123/asd would return an HTTP 200 with the body ["asd", "123", "asd"]
来源:https://stackoverflow.com/questions/64731635/can-a-controller-support-a-route-with-variable-string-parameters