web-dev-qa-db-ja.com

NET CORE MVC-ネストされたマルチパラメーター化されたルートを操作する方法

.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の検証メソッドが最初に呼び出され、次にメソッドon BuildingController?が呼び出されます。
  • 検証が失敗した場合に短絡し、ActionResultを返すcampusIdのコントローラーレベルの検証を行う方法はありますか?

編集:私が検証ロジックに言及するとき、私はAPIシグナルを意味します。 campusIdが有効か無効かを実際に決定するビジネスロジックではありません。

前もって感謝します!

15
James Dudley

ルートプレフィックスでプレースホルダーを使用する場合は、アクション自体にも含める必要があります。

[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との関係を確認するために使用できるサービス/リポジトリを用意することです。

15
Nkosi

campusIdと通信するときにユーザーにBuildingControllerを提供し、BuildingControllerを検証してcampusIdをDRY一種の方法です。

その場合は、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) 
      {...}
   }
}
3
Frank Fajardo