【问题标题】:NETCORE MVC - How to work with nested, multi-parameterized routesNET CORE MVC - 如何使用嵌套的多参数路由
【发布时间】:2017-08-01 22:10:41
【问题描述】:

寻找在 .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 内的每个操作方法中包含验证逻辑更好的方法。

  • 有没有办法在不同的控制器上级联多个 Action 方法?这样CampusController 上的验证方法会先被调用,然后再调用BuildingController 上的方法?
  • 有没有办法对campusId 进行控制器级别的验证,如果验证失败,它可能会短路并返回 ActionResult?

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

提前致谢!

【问题讨论】:

  • 您还可以为整个控制器类创建一个自定义过滤器属性,如[Authorize],以通过使用数据库、路由值、查询参数、登录用户等来验证每个 HTTP 请求。

标签: c# asp.net-core-mvc .net-core asp.net-core-routing


【解决方案1】:

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

[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 的关系(如果需要)。

【讨论】:

  • 这个解决方案对我来说最有意义,因为整个 campus 模型不需要在 BuildingController 类中;而只是需要执行一个简单的验证检查。谢谢!
  • 为什么不使用 FromRoute 而不是 FromQuery?
  • @Sam FromRoute 是正确的。我刚刚从 OP 复制了参数。这是我的疏忽。会更新。感谢您指出这一点。
【解决方案2】:

听起来您希望您的用户在与BuildingController 交谈时提供campusId,并且您的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) 
      {...}
   }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-01-04
    • 1970-01-01
    • 2016-12-29
    • 1970-01-01
    • 2018-10-30
    • 2017-04-22
    • 1970-01-01
    • 2017-04-09
    相关资源
    最近更新 更多