2013-04-18 3 views
11

私はASP.NET Web APIを使用して、私たちのサービス用にRESTful Web APIを設計しようとしています。私は、CRUD以外のアクションを適切なコントローラーアクションにルーティングする方法を理解することに苦労しています。私のリソースがドアだとしましょう。私は慣れ親しんだCRUDのことをすべて私のドアで行うことができます。RESTfulなASP.NET Web APIでCRUD以外のアクションをどのようにルーティングするのですか?

public class Door 
{ 
    public long Id { get; set; } 
    public string InsideRoomName { get; set; } 
    public string OutsideRoomName { get; set; } 
} 

私は自分のWeb APIを介して私の標準的なCRUD操作のすべてを行うことができます:ように

POST: http://api.contoso.com/v1/doors 
GET: http://api.contoso.com/v1/doors 
GET: http://api.contoso.com/v1/doors/1234 
GET: http://api.contoso.com/v1/doors?InsideRoomName=Cafeteria 
PUT: http://api.contoso.com/v1/doors/1234 
DELETE: http://api.contoso.com/v1/doors/1234 

とのは、私のドアのために、そのモデルがあるとしましょう。私が問題に遭遇するのは、私のドアに対して非CRUDアクションをモデル化する必要があるときです。私は自分のリソースに対してロックとアンロックの動詞をモデル化したいと思う。 ASP.NET articlesを読むと、カスタムアクションを使用するときにRPCスタイルの呼び出しに切り替えるように見えます。これは私にパスを与えます:

これは、リソースを示すための経路を目指すRESTの精神と矛盾するようです。私はリソースとして動詞をモデル化することができたとします

POST: http://api.contoso.com/v1/doors/1234/lockrequests 
POST: http://api.contoso.com/v1/doors/1234/unlockrequests 

この場合、私はまだお勧めします{コントローラ}を使用することができます/ {ID}/{アクション}が、私はまだ混在RPCを作成してるように思えます/ REST API。カスタムアクションをパラメータのリストに入れることは可能ですか、それともRESTインターフェースまで推奨されますか?

PUT: http://api.contoso.com/v1/doors/1234?lock 
PUT: http://api.contoso.com/v1/doors/1234?unlock 

私は、次のような、この呼び出しは、同様にクエリパラメータをサポート持つ必要性を予見できますどのように私は私のDoorsControllerにこの要求をマッピングするためにルートを作成します

PUT: http://api.contoso.com/v1/doors?lock&InsideRoomName=Cafeteria 

public class DoorsController : ApiController 
{ 
    public IEnumerable<Doord> Get(); 
    public Door Get(long id); 
    public void Put(long id, Door door); 
    public void Post(Door door); 
    public void Delete(long id); 

    public void Lock(long id); 
    public void Unlock(long id); 
    public void Lock(string InsideRoomName); 
} 

私は何であるかについて、ここではいくつかの誤った前提を作り、RESTのAPIの設計に関するベストプラクティスではないので、任意のガイダンスは、そこにも高く評価されていてもよいです。

国が利用可能な値の列挙です
public State State { get; set; } 

を、例えば:あなたはDoorオブジェクトへStateプロパティを追加することを検討できlock/unlockシナリオを処理するために

+0

GoogleではBloggerでREST APIを使用しています.RESTのアクションを使用しています。 https://developers.google.com/blogger/docs/3.0/reference/posts/publish – padibro

答えて

6

明確にするために

{ 
LockedFromOutsideRoom, 
LockedFromInsideRoom, 
Open 
} 

:状態は、APIを介して、あなたがドアで何かをする呼び出しを行うたびに渡されるようオブジェクトに状態を追加していることは、安らかな原則に反対するのではありません。

その後、各ロック/ロック解除時にドアの状態を変更するように、PUT/POSTのリクエストを送信します。それが更新される唯一の財産だとしてポストは、おそらく良いだろう:

POST: http://api.contoso.com/v1/doors/1234/state 
body: {"State":"LockedFromInsideRoom"} 
+0

WebApiConfig.csにカスタムルートを登録する必要がありますか?これはまだ私のコントローラがDoorsController :: State(ロングID、状態状態)を持つ{controller}/{id}/{action}のパターンに従っているようです。方法。 – JadeMason

+1

@JadeMason - このルートは正常に動作するはずです –

+0

@ JoannaTurban素敵な答え! 'PUT:http://api.contoso.com/v1/doors/1234 body:{" State ":" LockedFromInsideRoom "}'、あなたは実際に*アップデート*しています。状態。また、PUTの[idempotence](http://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Idempotent_methods_and_web_applications)と一貫性があります。このURLが要求されるたびに、まったく同じ結果が得られます。 –

1

RESTの観点から、あなたはおそらく、それ自体のリソースとしてロックを処理することにしたいです。こうすることで、ドアとは独立してロックを作成して削除することができます(おそらくドアの表示からロックエンドポイントを特定することもできます)。リソースのURLはおそらくドアのURLに関連していますが、RESTfulな観点からはこれは無関係です。 RESTはリソース間の関係に関するものなので、重要な部分はロックのURLがドアの表現から発見できることです。

2

RESTfulな原則から、CURD以外のアクションを管理するための 'ステータス'プロパティを導入するのが最善の方法かもしれません。しかし、私はそれが実際の生産開発を満たすとは思わない。

この種の質問に対する回答はすべて、あなたのAPIデザインをRESTfulにするための回避策を使用する必要があるようです。しかし、私の懸念は、本当にユーザーと開発者の双方にとって利便性があるということですか?

GoogleブログのAPI3.0デザインを見てみましょう:https://developers.google.com/blogger/docs/3.0/reference、それは非CURDアクションにロットURLを使用しています。

そして、これは興味深いです、

POST /blogs/blogId/posts/postId/comments/commentId/spam 

と説明が

ではスパムとしてコメントをマークします。これにより、コメントのステータスがスパムに設定され、デフォルトのコメントレンダリングで非表示になります。

コメントは、迷惑メールかどうかを示すステータスがありますが、JoannaTurbanが上記の回答と同様に設計されていないことがわかります。

ユーザーの観点から考えると、より便利です。 "状態"の構造とenum値を気にする必要はありません。そして、実際には、 "isItSpam"、 "isItReplied"、 "isItPublic"などのような "ステータス"の定義に多くの属性を入れることができます。ステータスに多くのものがある場合、デザインは不愉快になります。

ビジネスロジックの要件によっては、わかりやすい動詞を使用するために、「本当の」RESTfulなものにするのではなく、ユーザーと開発者にとってより生産的です。これは私の意見。

関連する問題