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" };
}
在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" };
}