Asp.net 具有多个可选参数调用不同操作的核心路由

Asp.net core Routing with multiple optional parameters calling different action

在Asp.netWebApi2

当调用 api/values/9b858599-7639-45da-acd6-a1323fb019b5 时调用 get 操作。

带有可选参数的操作。

当api/values/9b858599-7639-45da-acd6-a1323fb019b5?maxRecords=100 或 api/values/?maxRecords=100 调用 GetProducts 操作。

在Asp.net核心

但在 asp.net 核心中,当 api/values/9b858599-7639-45da-acd6-a1323fb019b5 被调用时,将调用 GetProducts 操作。我想在不更改现有 url 的情况下调用 Get 操作。

如何在 Asp.net 核心 2.0

中解决这个问题

控制器

[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
    //https://localhost:44323/api/values/9b858599-7639-45da-acd6-a1323fb019b5
    [HttpGet("{productId:Guid}", Order = 1)]
    public ActionResult<string> Get(Guid productId)
    {
        return "value1";
    }


    //https://localhost:44323/api/values/9b858599-7639-45da-acd6-a1323fb019b5?maxRecords=100
    //https://localhost:44323/api/values/?maxRecords=100
    [HttpGet("{startRecordId:Guid?}")]
    public ActionResult<IEnumerable<string>> GetProducts(Guid? startRecordId, int maxRecords, DateTimeOffset? minimumChangeDate = null)
    {
        return new string[] { "value1", "value2" };

    }

}

Startup.cs

app.UseMvc(routes =>
        {
            routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}");
            routes.MapRoute("DefaultApi", "api/{controller}/{id?}");
        });

您的 URI 不遵循 RESTful 约定。坦率地说,我一开始看不出你是如何做到这一点的,因为同样的问题应该会导致 ASP.NET Web Api,但你可能只是对路由的方式感到幸运在 ASP.NET Web Api 中完成。 ASP.NET 核心处理路由的方式完全不同。

无论如何,多个产品列表的路由不应在实际 URI 中包含 id。换句话说:

/api/values - Multiple values
/api/values/{id} - Single value

对于多条记录的过滤、排序等,这些应该是查询字符串的一部分。这包括 startRecordId:

/api/values?startRecordId={id}

消除路线中的歧义,您就没有问题了。总之,您不能在同一路径段中让两条路线都接受 Guid,即使它在一条路线上是可选的。将 startRecordId 移动到查询字符串中,无论如何这是正确的方法,你就可以开始了。

虽然不理想,但这是一个临时鞋拔,直到您可以更新客户端调用。你可以试试这个,如果你可以假设你必须有一个maxRecords QueryString。因为如果它默认为 0 它是无用的,除非你在它是 0 的情况下有适当的逻辑。

    //https://localhost:44323/api/values/9b858599-7639-45da-acd6-a1323fb019b5
    [HttpGet("{productId:Guid}", Order = 1)]
    public ActionResult<string> Get(Guid productId)
    {
        return "value1";
    }


    //https://localhost:44323/api/values/9b858599-7639-45da-acd6-a1323fb019b5?maxRecords=100
    //https://localhost:44323/api/values/?maxRecords=100
    [HttpGet("{startRecordId:Guid?}")]
    public ActionResult<IEnumerable<string>> GetProducts(Guid? startRecordId, [FromQuery] int maxRecords, [FromQuery] DateTimeOffset? minimumChangeDate = null)
    {
        if (!Request.GetDisplayUrl().Contains(nameof(maxRecords)) &&
            startRecordId.HasValue)
        {
            return Get(startRecordId.Value);
        }

        return new string[] { "value1", "value2" };

    }

您可以结合您的操作并根据具有提供值的参数更改行为;

    //https://localhost:44323/api/values/9b858599-7639-45da-acd6-a1323fb019b5
    //https://localhost:44323/api/values/9b858599-7639-45da-acd6-a1323fb019b5?maxRecords=100
    //https://localhost:44323/api/values/?maxRecords=100
    [HttpGet("{startRecordId:Guid?}")]
    public ActionResult<IEnumerable<string>> GetProducts(Guid? startRecordId, int? maxRecords, DateTimeOffset? minimumChangeDate = null)
    {
        if (startRecordId.HasValue && !maxRecords.HasValue)
            return "value";
        else
            return new string[] { "value1", "value2" };

    }