2

次の2つのPOSTシナリオを検討してください。

  1. POST /localhost/api/-エンティティを挿入し、200を返します
  2. POST /localhost/api/1324-悪いリクエスト、400を返す

シナリオ2に対処するための最良の方法は何ですか?

私は何もせず、私のAPIを使用している開発者がこれが間違っていることを理解すると思いますか?これを処理するためにPOSTメソッドにコードを追加して、これが悪いリクエストであることを伝えますか?

悪いリクエストを返すことはおそらくここで行うのが最善のことだと思います。それは私が実装することになったものですが、私がまだ発見していないこれを達成するためのより良い方法があるかもしれないと感じています。

私の現在のコードは次のとおりです。

[HttpPost]
public HttpResponseMessage Post(MyEntity entity) {
  if(entity.Id != null)
      throw new HttpResponseException(HttpStatusCode.BadRequest);

  MyEntity saved = repository.Insert(entity);

  HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created, saved);
  response.Headers.Location = new Uri(Request.RequestUri, new Uri(saved.Id.ToString(), UriKind.Relative));

  return response;
}

// Prevents any attempt to POST with a Guid in the url
[HttpPost]
public void Post(Guid Id) {
  throw new HttpResponseException(HttpStatusCode.BadRequest);
}

ありがとう!

4

3 に答える 3

3

あなたのしていることは正しいようです。私はそれらの長さに行くかどうかいくつかの疑問がありますが。

修正

私は言った

この追加のメソッドを実装していなかった場合、ルーティングは失敗し、通常は404が返されます。この動作をそのままにしておくことをお勧めします。

しかし、あなたは正しいです:

上記のように動作させるには、つまりデフォルトで404に設定するには、次のルート構成が必要になります。

       config.Routes.MapHttpRoute(
            name: "DefaultCollectionApi",
            routeTemplate: "api/{controller}",
            defaults: new { },
            constraints: new { httpMethod = new HttpMethodConstraint(HttpMethod.Post) }
            );

        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new {  },
            constraints: new { httpMethod = new HttpMethodConstraint(HttpMethod.Get, HttpMethod.Put, HttpMethod.Delete) }
            );

既存のアプローチをわずかに改善するには

ただし、動詞とルートの組み合わせのポリシングを開始する必要があると感じた場合は、このロジックをActionFilterAttributeに移動する価値があるかもしれません。

このルートを一番上に追加すると、すべてのルートで慣例により使用すると仮定すると、のキーを使用して値を検索し、400例外を発生させる"id"フィルターをすばやくまとめることができます。RouteValuesid

public class ValidVerbAndRouteAttribute : ActionFilterAttribute
{
    public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
    {
        object id;
        if (actionExecutedContext.ActionContext.ActionArguments.TryGetValue("id", out id) &&
            actionExecutedContext.Request.Method == HttpMethod.Post)
        {
            throw new HttpResponseException(HttpStatusCode.BadRequest);
        }
    }
} 
于 2013-02-26T12:38:18.687 に答える
2

あなたがそれを扱っている方法は現在正しいようです。これは標準の入力データ検証であり、この検証がRESTful用語で失敗した場合に使用する正しいステータスコードは400です。

于 2013-02-26T12:25:59.607 に答える
1

あなたがそれをするために結んでいる方法は正しいです、しかしあなたが望むならあなたが選ぶための別の方法があります。次のようなシグネチャでアクションを指定するよりも、ルートを構成して、具体的なアクションを呼び出す必要があることを示すことができます。

[HttpPost]
public HttpResponseMessage PostEntity([FromBody]MyEntity entity) {...}

これにより、このアクションの他の署名を使用して呼び出しが不可能になり、例外が発生します。

ルート:

            config.Routes.MapHttpRoute(
            name: "ActionApi",
            routeTemplate: "api/{controller}/{action}/{id}",
            defaults: new { id = RouteParameter.Optional });

また、例外処理については、例外タイプのマッピングのセットと、好みに応じたHttpStatusCode表現を含む例外フィルターをお勧めします。

于 2013-02-26T12:41:45.840 に答える