HTTP-запрос карты / маршрута к конечной точке на основе значения параметра запроса? asp. net ядро ​​3.x - PullRequest
1 голос
/ 20 апреля 2020

У меня есть клиент, которому нужно будет использовать один и тот же базовый 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}");
    }
}

1 Ответ

1 голос
/ 21 апреля 2020

Вам необходимо настроить 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.Controller :

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

}

Ссылка:

{ ссылка }

...