2017-08-01 2 views
5

Suchen Sie nach Best Practices beim Arbeiten mit verschachtelten Routen in .NET Core MVC.NETCORE MVC - So arbeiten Sie mit verschachtelten, multiparametrisierten Routen

die CampusController.cs arbeitet mit einem Basismodell Lassen Sie sagen:

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

Und BuildingController.cs arbeitet mit einem Kind Modell:

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

Wenn buildingId Karten direkt auf die Datenbank es campusId auch wenn die vorgesehenen abgerufen könnte ist nicht der Elternteil. Um die URL beim Aufrufen von /api/campus/{campusId}/building/{buildingId} sauber zu halten, möchte ich {campusId} validieren und ein 4xx-codiertes IActionResult zurückgeben, wenn es ungültig ist. Es muss einen besseren Weg geben, als die Validierungslogik in jede Aktionsmethode in BuildingController einzuschließen.

  • Gibt es eine Möglichkeit, mehrere Aktionsmethoden auf verschiedenen Controllern zu kaskadieren? So dass eine Validierungsmethode auf CampusController zuerst aufgerufen würde und wiederum eine Methode auf BuildingController aufrufen?
  • Gibt es eine Möglichkeit, eine Verifizierung auf Controller-Ebene von campusId zu erhalten, die einen Kurzschluss verursachen und ein ActionResult zurückgeben könnte, wenn die Validierung fehlschlägt?

EDIT: Wenn ich auf Validierungslogik beziehe, meine ich API-Signale; nicht die Geschäftslogik, die tatsächlich feststellt, ob campusId gültig ist/ist.

Vielen Dank im Voraus!

Antwort

5

Wenn Platzhalter in der Route Präfix würden Sie es auch in der Aktion enthalten müssen sich

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

Wenn etwa wiederholt Code besorgt für die Validierung dann eine Basis-Controller für Campus bezogene Anfrage erstellen und haben eine gemeinsame Validierung Methode.

Eine weitere Option ist ein Service/Repository, mit dem die Campus-ID und ihre Beziehung zur angegebenen Gebäude-ID bei Bedarf überprüft werden können.

+1

Diese Lösung ist für mich am sinnvollsten, da das gesamte "Campus" -Modell nicht in der "BuildingController" -Klasse sein muss; Es muss nur eine einfache Validierungsprüfung durchgeführt werden. Vielen Dank! –

+0

Warum nicht FromRoute anstelle von FromQuery verwenden? – 000

+0

@Sam 'FromRoute' ist korrekt. Ich hatte gerade die Parameter vom OP kopiert. es war ein Versehen meinerseits. Werde Dich auf dem Laufenden halten. Danke, dass du es aufgezeigt hast. – Nkosi

2

Es klingt wie Sie Ihre Nutzer wollen ein campusId zur Verfügung zu stellen, wenn sie die BuildingController sprechen, und Ihre BuildingControllercampusId in einer trockenen Art und Weise zu validieren.

Wenn das der Fall ist, können Sie ein Eingabemodell für Ihre BuildingController Methoden erstellen:

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

Dann können Sie MVC binden Benutzereingaben an diesem Modell lassen.

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