NETCORE MVC - How to work with nested, multi-parameterized routes

Look for best practices for working with nested routes in .NET Core MVC.

Let's say CampusController.cs works with the base model:

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

And BuildingController.cs works with the child model:

 [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) } 

If the buildingId mapped directly to the database, it can be restored even if the provided campusId not a parent. To clear the url when calling /api/campus/{campusId}/building/{buildingId} , I would check {campusId} and return a 4xx encoded IActionResult if it is not valid. There should be a better way than incorporating validation logic into every action method inside the BuildingController .

  • Is there a way to cascade multiple Action methods on different controllers? So that the check method on CampusController called first and in turn call the method on BuildingController ?
  • Is there a way to test at the campusId controller campusId at the controller level, which can short circuit and return an ActionResult if the test is not completed?

EDIT: when I refer to the validation logic, I mean the API signals; not the business logic that actually determines if campusId / is invalid.

Thanks in advance!

+5
source share
2 answers

If you use the placeholder in the route prefix, you will also need to enable it in the action itself

 [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 } } 

If you are concerned about the re-verification code, create a base controller for the campus-related request and get a general verification method.

Another option is to have a service / repository that can be used to verify the campus ID and its relationship to the provided building ID, if necessary.

+5
source

It looks like you want your users to provide campusId when talking to the BuildingController and your BuildingController to check the campusId dry way.

In this case, you can create an input model for your BuildingController methods:

 public class BuildingIdInput { [Required] public int? CampusId { get; set; } [Required] public int? BuildingId { get; set; } } 

Then you can let MVC bind the user to this model.

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

Source: https://habr.com/ru/post/1270459/


All Articles