web-dev-qa-db-ja.com

REST APIメソッドの複合キー

次のユースケースのRESTful API設計のベストプラクティスを探しています。

ドメインオブジェクトビークル:

class Vehicle {
    private String vehicleType;
    private String colour;
    private String transmission;
    private String yearOfIssue;
}

オブジェクトの例:

Vehicle = {vehicleType : 'Car', colour : 'Red', transmission : 'Automatic', yearOfIssue : '2008'};

このドメインモデルでは、単一のフィールドの一意の識別子(vehicleIdなど)はありませんが、オブジェクトのすべてのフィールドが一緒に主キーを形成します(この制約はデータベースレイヤーにあります)。

このドメインモデルを変更して単一のフィールドの一意の識別子を追加する柔軟性はありません。

だから私の質問は次のとおりです-このドメインオブジェクトの上に単純なREST APIを追加して、車両の作成、更新、削除、および取得にシンプルな機能を提供する場合、ベストプラクティスは何ですか?これらのメソッドのPATHエンドポイントについては?

上記の例に続いて、ドメインモデルに単一のフィールドの一意の識別子vehicleIdがある場合、次のエンドポイントを想像できます。

GET /vehicles/:vehicleId
PUT /vehicles/:vehicleId
DELETE /vehicles/:vehicleId

私は複合キーのこれと同様に存在するパターンを認識していません:

GET /vehicles/:vehicleTypecolourtransmissionyearOfIssue
GET /vehicles/CarRedAutomatic2008

正しくないようです。

この使用例について従うべき良いパターンに関するアドバイスがあれば、大歓迎です。

ありがとう

23
JoshDavies

一般的なREST標準に従って、各エンドポイントはリソースを公開し、クライアントはそれらをhttp動詞で処理できます。この例では、リソースは車両であり、クライアントはGETを使用してサーバーからデータをフェッチしています。理想的には、各リソースは一意の(単一の)キーで一意に識別される必要があります。

ただし、リソース(車両)には単一の値の一意のキーがなく、システムで変更することはできません。この場合でも、他の標準のhttp呼び出しと同様に、リソースを識別するために必要なすべてのパラメーターを使用してGET呼び出しを行うことができます。

GET /vehicles?type=Car&color=Red&transmission=Automatic&manufactureYear=2008

使用しているテクノロジー/プラットフォーム。メソッドのカスタムルートを作成できる場合は、次のようなカスタムルートを作成できます。

new route("/vehicles/{type}/{color}/{transmission}/{manufactureYear}")

そしてあなたのサービスを

GET /vehicles/Car/Red/Automatic/2008

これの良いところは、URIが短くなることです。しかし一方で、[1]このタイプのすべてのメソッド/リソースでは、カスタムルートを作成する必要があります。[2]このURIは、特定のメソッドとルートの知識がない限り、あまり意味がありません。

16
Arghya C

ASP.NET Coreでは、通常、次のような複合キーを表します。

POST /vehicles/(car:red:automatic:2008)

または

POST /vehicles/(car|red|automatic|2008)

フレームワークは、これらを指定された順序でアクションパラメータにマッピングすることに問題はありません。

_[HttpPut("vehicles/({car}:{color}:{trans}:{year})")]
public async Task<IActionResult> Add(
    string car, string color, string trans, int year, [FromBody] Vehicle request)
{
    await Task.CompletedTask;

    return Ok();
}
_

リクエストの例:PUT /vehicles/(Ford:Ranger:100% genuine:2000)

enter image description here

6
bugged87

RESTfulになるには、クラスを拡張する単一の一意の識別子を作成する必要があります。

class Vehicle {
    public int vechicleId { get; set; }
    public string vehicleType { get; set; }
    public string colour { get; set; }
    public string transmission { get; set; }
    public string yearOfIssue { get; set; }
}

次に、HTTP:Get http:// mysite/vehicles/3842 を使用してアクセスできます。ただし、データベースをシードまたは更新する場合は特に、内部の一意の識別子にアクセスできない場合があります。私は同様の問題に遭遇し、REST動詞を使用するために、人間と外部システムがレコードにアクセスしやすくするために、外部識別子を含めます。

class Vehicle {
    public int vechicleId { get; set; }
    public string externalId { get; set; }
    public string vehicleType { get; set; }
    public string colour { get; set; }
    public string transmission { get; set; }
    public string yearOfIssue { get; set; }
}

次に、動詞は次のようになります:HTTP:Get http:// mysite/vehicles/externalId/sedanbluemanual2015 。すべてのデータがメッセージの本文に含まれている必要があるため、URIを解析する必要はありません。文字列が車両を一意に識別することを確認する必要があるだけです。

[HttpPut("externalId/{externalId}")]
public IActionResult PutVehicle([FromRoute] string externalId, [FromBody] JObject jObject)
{
    // See if the record exists already.
    var oldVehicle = (from v in vehicles
                       where vehicle.ExternalId == externalId
                       select v).FirstOrDefault();
    if (oldVehicle != null)
    {
        <insert new vehicle>
    }
    else
    {
        <update old vehicle>
    }
1
Quarkly