Can a Controller support a route with variable string parameters?

我们两清 提交于 2021-02-19 08:24:47

问题


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

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