Как включить строку запроса в разрешение маршрута, чтобы разрешить несколько действий с одним и тем же методом, маршрутом и строкой запроса? - PullRequest
1 голос
/ 20 марта 2020

Я конвертирую ASP. NET MVC (. NET Framework) приложение в ASP. NET Core MVC. Это строго преобразование, я не могу вносить какие-либо критические изменения, следовательно, я не могу изменить ни маршруты, ни методы. Я не могу сопоставить ту же функциональность в ASP. NET Core MVC.

Работает ASP. NET MVC:

  [HttpPut]
  [Route("status")]
  public async Task<IHttpActionResult> UpdateStatusByOrderGuid([FromUri] Guid orderGUID, [FromBody] POST_Status linkStatusModel)
  {

  }

  [HttpPut]
  [Route("status")]
  public async Task<IHttpActionResult> UpdateStatusById([FromUri] Guid id, [FromBody] POST_Status linkStatusModel)
  {

  }

Не работает , ASP. NET Core MVC.

Я получаю сообщение об ошибке:

Microsoft.AspNetCore.Routing.Matching.AmbiguousMatchException: запрос соответствует нескольким конечным точкам

Код:

    [HttpPut]
    [Route("status")]
    public async Task<IActionResult> UpdateStatusByOrderGuid([FromQuery] Guid orderGUID, [FromBody] POST_Status statusModel)
    {

    }

    [HttpPut]
    [Route("status")]
    public async Task<IActionResult> UpdateStatusById([FromQuery] Guid id, [FromBody] POST_Status statusModel)
    {

    }

Мне нужно включить параметры запроса, когда он решает, какой маршрут. Он должен совпадать в зависимости от того, есть ли в строке запроса orderGUID или id.

Спасибо.

Ответы [ 2 ]

2 голосов
/ 20 марта 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.Контроллер:

[HttpPut]
[Route("status")]
[QueryStringConstraint("orderGUID",true)]
[QueryStringConstraint("id", false)]
public void UpdateStatusByOrderGuid([FromQuery] Guid orderGUID,[FromBody]POST_Status model)
{

}

[HttpPut]
[Route("status")]
[QueryStringConstraint("id", true)]
[QueryStringConstraint("orderGUID", false)]
public void UpdateStatusById([FromQuery] Guid id, [FromBody]POST_Status model)
{

}

3.Startup.cs:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    //...
    app.UseMvc(routes =>
    {
        routes.MapRoute(
            name: "default",
            template: "{controller=Home}/{action=Index}/{id?}");
    });
}

Результат: enter image description here

1 голос
/ 26 марта 2020

Почему бы вместо этого не использовать одну конечную точку? Вам не нужно передавать Guid, так как это операция GET, вы можете передать строки и привести их позже. Таким образом, вы можете отправить один или другой параметр.

[HttpPut]
[Route("status")]
public async Task<IActionResult> UpdateStatus([FromBody] POST_Status statusModel, [FromQuery] string orderGUID = null, [FromQuery] string id = null)
{
    if (!string.IsNullOrEmpty(orderGUID))
    {
        // UpdateStatusByOrderGuid implementation here
        // Guid guid = Guid.Parse(orderGUID);

    }
    else if (!string.IsNullOrEmpty(id))
    {
        // UpdateStatusById implementation here
        // Guid guid = Guid.Parse(id);
    }
    else
    {
        throw new ArgumentException("No valid GUID.");
    }
}

Эта конечная точка должна быть совместима с указанным вами сценарием ios.

...