NETCORE MVC - 如何使用嵌套的多参数化路由

Jam*_*ley 14 c# asp.net-core-mvc .net-core asp.net-core-routing

在.NET Core MVC中使用嵌套路由时寻找最佳实践.

假设CampusController.cs使用基本模型:

[Route("api/campus/")]
public class CampusController : Controller
{
    ...
    [HttpGet]
    [Route("{campusId}")]
    public IActionResult GetCampusInfo ([FromQuery]int campusId) { ... }
}
Run Code Online (Sandbox Code Playgroud)

BuildingController.cs与儿童模型一起使用:

[Route("api/campus/{campusId}/building")]
public class BuildingController : Controller
{
    ...
    [HttpGet]
    [Route("{buildingId}")]
    public IActionResult GetBuilding ([FromQuery]int buildingId) { ... }

    [Route("{buildingId}/")]
    public IActionResult GetBuilding ([FromQuery]int buildingId) { ... }
    ....
    (more Action Methods)
}
Run Code Online (Sandbox Code Playgroud)

如果buildingId直接映射到数据库,即使提供campusId的不是父级,也可以检索它.为了在调用时保持URL清洁,/api/campus/{campusId}/building/{buildingId}我想验证{campusId}并返回4xx编码的IActionResult,如果它无效的话.必须有一种比在每个Action Method里面包含验证逻辑更好的方法BuildingController.

  • 有没有办法在不同的控制器上级联多个Action方法?因此,CampusController首先调用验证方法,然后调用方法BuildingController
  • campusId如果验证失败,有没有办法让控制器级验证可以短路并返回ActionResult?

编辑:当我提到验证逻辑时,我指的是API信号; 而不是实际确定campusId是否无效的业务逻辑.

提前致谢!

Nko*_*osi 16

如果在路由前缀中使用占位符,则还需要将其包含在操作本身中

[Route("api/campus/{campusId:int}/building")]
public class BuildingController : Controller {
    //...

    [HttpGet]
    [Route("{buildingId:int}")] // Matches GET api/campus/123/building/456
    public IActionResult GetBuilding ([FromRoute]int campusId, [FromRoute]int buildingId) { 
        //... validate campus id along with building id 
    }    
}
Run Code Online (Sandbox Code Playgroud)

如果担心重复的验证代码,则为校园相关请求创建一个基本控制器,并具有共享验证方法.

另一种选择是拥有一个服务/存储库,可用于验证校园ID及其与所提供的建筑物ID的关系(如果需要).


Fra*_*rdo 6

听起来您希望您的用户campusId在与 交谈时提供一个BuildingController,并且您BuildingControllercampusId一种 DRY 的方式进行验证。

如果是这种情况,您可以为您的BuildingController方法创建一个输入模型:

public class BuildingIdInput
{
   [Required]
   public int? CampusId { get; set; }
   [Required]
   public int? BuildingId { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

然后你可以让 MVC 将用户输入绑定到这个模型。

[Route("api/campus")]
public class BuildingController : Controller
{
   [HttpGet]
   [Route("{campusId}/building/{buildingId}")]
   public IActionResult GetBuilding (BuildingIdInput input) 
   { 
      if (ModelState.IsValid) 
      {...}
   }
}
Run Code Online (Sandbox Code Playgroud)