5

次の手順でこの問題を見つけました。

  1. インストールされたプロジェクト テンプレートを使用して新しい WebApi プロジェクトを作成する

  2. Controllers/ValuesController.cs に移動します。次のような 2 つのGetメソッドがあります。

    public IEnumerable<string> Get() // これはGetAll関数を提供します

    public string Get(int id) // これはGetOneById です

  3. 2 つの API メソッドを 1 つに組み合わせることができると思うので、この設計は好きではありません。

    public IEnumerable<string> Get(string ids)ids が null の場合、すべてのレコードを返します。それ以外の場合は、ids (id1、id2、id3 のようになります) によって結果を返します。

ルートも変更しました:

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

これですべての準備が整ったと思います。ただし/values、ブラウザーで (ids パラメーターを指定せずに) にアクセスすると、次のデフォルト値を追加するまで、「アクションが見つかりませんでした」と言われましたids

public IEnumerable<string> Get(string ids = null)

これからは、すべてが期待どおりに機能します。それでもdefaults、ルート内のパラメーターを移動できません。つまり、コードは ids パラメータをオプションとして 2 回宣言しています

method にある MVC4 のソース コードを調べると、適切な actionSystem.Web.Http.Controllers.ActionSelectorCacheItem.FindActionUsingRouteAndQueryParametersを見つけるときに、ルートで定義されたオプションのパラメーターが無視されていることがわかります。個人的には、これは本当に悪いことだと思います。回避策は非常に簡単です。それとも、ルートとアクション メソッドの関係を誤解していましたか? ルートは、リクエストが対応するアクションを見つけるのを助けるために使用されるルールであると考えていますが、「パラメーターはオプションです」はまさにルールの一部です。

4

2 に答える 2

4

これは比較的単純な解決策のように感じますが、根本的な原因は、'GetAll' と 'GetOneById' の両方を同じメソッドにロールしようとしているからだと思います。

コントローラーでメソッドを分割したい場合は、ルート構成を問題から除外できます。私見これはそれほど悪いことではありません。懸念の分離の原則に準拠しています。また、返すオブジェクトにアクセスするためのロジックを集中化できるため、コードの重複も意味しません。

これらのコントローラー メソッドは、ルート構成を調整することなく、必要なルートを提供する必要があります。

[HttpGet]
public IEnumerable<string> GetAll()
{
    return GetStrings(new int[]{});
}

[HttpGet]
public string GetOneById(int id)
{
    return GetStrings(new int[]{id}).FirstOrDefault();
}

private IEnumerable<string> GetStrings(int[] ids)
{
     return // fetch strings using int array
}
于 2012-11-23T10:04:40.157 に答える
1

値をクエリ文字列として持つオプションがあります

public class PaymentsController : ApiController {
        [HttpGet]
        public Person GetValues(string ids = null)
        {
            return new Person() { FirstName = "Michael" };
        }
    }

    public class Person
    {
        public string FirstName { get; set; }
    }
}

両方でこのルートにアクセスできました:

  1. /api/payments/getvalues/?ids=123
  2. /api/支払い/getvalues/

注:デフォルト以外の特別なルーティングなし

于 2012-11-23T10:00:45.887 に答える