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

C# NETCORE MVC-如何使用嵌套的多参数路由,c#,asp.net-core-mvc,.net-core,asp.net-core-routing,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) { ...

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

让我们假设
CampusController.cs
与基本模型一起工作:

[Route("api/campus/")]
public class CampusController : Controller
{
    ...
    [HttpGet]
    [Route("{campusId}")]
    public IActionResult GetCampusInfo ([FromQuery]int campusId) { ... }
}
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)
}
如果
buildingId
直接映射到数据库,则即使提供的
campusId
不是父项,也可以检索到该数据库。为了在调用
/api/campus/{campusId}/building/{buildingId}
时保持URL干净,我想验证
{campusId}
,如果无效,则返回4xx编码的IActionResult。必须有一种比在
BuildingController
中的每个操作方法中包含验证逻辑更好的方法

  • 有没有办法在不同的控制器上级联多个动作方法?因此,首先调用
    CampusController
    上的验证方法,然后调用
    BuildingController
    上的方法
  • 是否有办法对
    campusId
    进行控制器级验证,如果验证失败,该验证可能会短路并返回ActionResult
编辑:当我提到验证逻辑时,我指的是API信号;而不是实际确定campusId是否有效的业务逻辑


提前谢谢

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

[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 
    }    
}
如果担心重复的验证代码,那么为校园相关请求创建一个基本控制器,并拥有一个共享的验证方法


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

听起来您希望用户在与
建筑控制器交谈时提供
校园id
,和您的
BuildingController
以一种干燥的方式验证
campusId

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

public class BuildingIdInput
{
   [Required]
   public int? CampusId { get; set; }
   [Required]
   public int? BuildingId { get; set; }
}
然后,您可以让MVC将用户输入绑定到此模型

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

这个解决方案对我来说最有意义,因为整个
校园
模型不需要在
BuildingController
类中;而只是需要进行一次简单的验证检查。谢谢为什么不使用FromRoute而不是FromQuery?@Sam
FromRoute
是正确的。我刚从OP复制了参数。这是我的疏忽。将更新。感谢您指出。您还可以为整个控制器类创建一个自定义筛选器属性,如
[Authorize]
,以通过使用数据库、路由值、查询参数、登录用户等来验证每个HTTP请求。