Сопоставить / направить HTTP-запрос к конечной точке на основе значения параметра запроса? asp.net core 3.x

У меня есть клиент, которому нужно будет использовать один и тот же URL-адрес базовой конечной точки для нескольких запросов с использованием остальных вызовов HttpGet, каждый из которых имеет уникальные параметры и значения запроса. Функция, которую мне нужно отобразить для каждого запроса, будет определяться значением, предоставленным параметром запроса "request". Возможно ли это сделать внутри app.UseEndpoints (), атрибутов функций конечной точки или аналогичного простого решения?

Я немного новичок в этой части, и в документации нет примера для этого. Что у меня пока (не работает):

Startup.cs

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllerRoute(
            name: "test1",
            pattern: "serviceapi",
            constraints: new { request = "test1" }, //map action if param "request" value is "test1"?
            defaults: new { controller = "ServiceApi", action = "TestRequest1" }
        );
        endpoints.MapControllerRoute(
            name: "test2",
            pattern: "serviceapi",
            constraints: new { request = "test2" }, //map action if param "request" value is "test2"?
            defaults: new { controller = "ServiceApi", action = "TestRequest2" }
        );
    });

что я хочу, это когда я использую почтальон для отправки запроса на получение в "{{url}} / api / serviceapi /? request = test1 & uniqueparam1 = foo", он запускается код в моем ServiceApi.TestRequest1 ()

[Route("api/[controller]")]
ServiceApiController.cs

    [HttpGet]
    public async Task<IActionResult> TestRequest1([FromQuery]string request, [FromQuery]string uniqueparam1)
    {
        return Ok($"TestRequest1: {request} - {uniqueparam1}");
    }

    [HttpGet]
    public async Task<IActionResult> TestRequest2([FromQuery]string request, [FromQuery]string uniqueparam2, [FromQuery]string uniqueparam3)
    {
        return Ok($"TestRequest2: {request} - {uniqueparam2}, {uniqueparam3}");
    }

Ошибка, которую я получаю сейчас с этим кодом, заключается в том, что обе функции были кандидатами: «Microsoft.AspNetCore.Routing.Matching.AmbiguousMatchException: запрос соответствует нескольким конечным точкам».

Спасибо!

------ ОБНОВЛЕНИЕ ------

Благодаря ответу Рены мне удалось заставить это работать:

[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class RequestValueConstraintAttribute : ActionMethodSelectorAttribute
{
    public string RequestValue { get; private set; }

    private readonly string _requestParam = "request";

    public RequestValueConstraintAttribute(string requestValue)
    {
        RequestValue = requestValue;
    }

    public override bool IsValidForRequest(RouteContext routeContext, ActionDescriptor action)
    {
        return (string)routeContext.HttpContext.Request.Query[_requestParam] == RequestValue;
    }
}

ServiceApiController.cs

[Route("api/[controller]")]
[ApiController]
public class ServiceApiController : ControllerBase
{
    [RequestValueConstraint("test1")] //uses this endpoint function if param "request" value is "test1"
    [HttpGet]
    public async Task<IActionResult> TestRequest1([FromQuery]string request, [FromQuery]string uniqueparam1)
    {
        return Ok($"TestRequest1: {request} - {uniqueparam1}");
    }

    [RequestValueConstraint("test2")] //uses this endpoint function if param "request" value is "test2"
    [HttpGet]
    public async Task<IActionResult> TestRequest2([FromQuery]string request, [FromQuery]string uniqueparam2, [FromQuery]string uniqueparam3)
    {
        return Ok($"TestRequest2: {request} - {uniqueparam2}, {uniqueparam3}");
    }
}

person FishyDev    schedule 20.04.2020    source источник


Ответы (1)


Вам необходимо настроить ActionMethodSelectorAttribute:

1.QueryStringConstraintAttribute :

[AttributeUsage(AttributeTargets.Method,AllowMultiple =true)]
public class QueryStringConstraintAttribute : ActionMethodSelectorAttribute
{
    public string ValueName { get; private set; }
    public bool ValuePresent { get; private set; }
    public QueryStringConstraintAttribute(string valueName,bool valuePresent)
    {
        this.ValueName = valueName;
        this.ValuePresent = valuePresent;
    }
    public override bool IsValidForRequest(RouteContext routeContext, ActionDescriptor action)
    {
        var value = routeContext.HttpContext.Request.Query[this.ValueName];
        if(this.ValuePresent)
        {
            return !StringValues.IsNullOrEmpty(value);
        }
        return StringValues.IsNullOrEmpty(value);
    }
}

2.Контроллер :

[Route("api/[controller]")]
[ApiController]
public class ValuesController : Controller
{
    [QueryStringConstraint("uniqueparam1", true)]
    [QueryStringConstraint("uniqueparam2", false)]
    [HttpGet]
    public async Task<IActionResult> TestRequest1([FromQuery]string request, [FromQuery]string uniqueparam1)
    {
        return Ok($"TestRequest1: {request} - {uniqueparam1}");
    }
    [QueryStringConstraint("uniqueparam2", true)]
    [QueryStringConstraint("uniqueparam1", false)]
    [HttpGet]
    public async Task<IActionResult> TestRequest2([FromQuery]string request, [FromQuery]string uniqueparam2, [FromQuery]string uniqueparam3)
    {
        return Ok($"TestRequest2: {request} - {uniqueparam2}, {uniqueparam3}");
    }
}

3.Startup.cs:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    //...   
    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();                
    });

}

Ссылка:

https://stackoverflow.com/a/60770054/11398810

person Rena    schedule 21.04.2020