2012-08-22 14 views
15

プロジェクト内のどのモデルもサポートする汎用Web APIを使用できますか?任意のモデルをサポートする汎用Web APIコントローラ

class BaseApiController<T> :ApiController 
{ 
    private IRepository<T> _repository; 

    // inject repository 

    public virtual IEnumerable<T> GetAll() 
    { 
     return _repository.GetAll(); 
    } 

    public virtual T Get(int id) 
    { 
     return _repositry.Get(id); 
    } 

    public virtual void Post(T item) 
    { 
     _repository.Save(item); 
    } 
    // etc... 
} 

class FooApiController : BaseApiController<Foo> 
{ 
    //.. 

} 

class BarApiController : BaseApiController<Bar> 
{ 
    //.. 
} 

これは良いアプローチでしょうか?

すべての後、私はちょうどCRUDメソッドを繰り返しmは?この基本クラスを使って私の仕事をすることはできますか?

これはOKですか?あなたはこれをしますか?どんな良いアイデアですか?

+0

こんにちは、これは古い質問ですが、どのように汎用アクションメソッドを呼び出すことができたか説明できますか?ルーティングルールだけでこれを達成できるようには見えません。私は大いに感謝します。 – Brett

答えて

22

私が何かアップし、クライアントにデモするために実行されている取得するための小規模なプロジェクトのためにこれをやりました。ビジネスルール、検証、その他の考慮事項の詳細がわかり次第、私は基本クラスからCRUDメソッドをオーバーライドしなくて済むようになり、長期的な実装としては機能しませんでした。

すべてが同じタイプのIDを使用していない(私は既存システムで働いていた)ので、私は、ルーティングの問題に走りました。いくつかのテーブルはintプライマリキーを持ち、一部はstrings、その他はguidsでした。

私はそれにも問題がありました。結局、私が最初にやったときに滑らかに見えましたが、実際に実際の実装でそれを使用することは、別の問題であることが判明しました。

+6

よく、あなたはそれを 'IIdentifier 'と呼んで、異なる種類のIDを表現することができます。 – DarthVader

+0

真実ではあるが、後ろから見ても、私はCRED操作をプリエンプティブに1つの汎用コントローラにリファクタリングしようとすることから恩恵を受けたとはまだ思っていません。それはあとで開発の頭痛を引き起こしました。 –

+0

あなたがグリーンフィールドなら、同じタイプのすべての "Id"を持つべきではない理由はありません。 – LastTribunal

5

間違いなく可能です。私は前にそれを行う理由は一度もありませんでしたが、それがあなたの状況に合っていれば、それは良いことです。

あなたのモデルのすべてが保存され、まったく同じ方法で検索することができた場合は、おそらく彼らはただ、すべてかかわらず、代わりに同じコントローラにすべきですか?

+0

なぜそれがうまくいかないのですか?本質的にほとんどの場合、すべてのドメインモデルに対して同じ操作を使用し、それらを何度も繰り返すだけです。 – DarthVader

+1

あなたはそれが可能かどうか尋ねたので、私はそれに答えました:)確かに、私は質問の残りの部分には足りなかったと思う、私はちょうど私の答えを削除するかもしれません... – eouw0o83hf

+0

私はあなたの答えを削除していない – DarthVader

0

前の回答で述べたように、それは絶対に可能です。これは良いアプローチであり、確かに良いアーキテクチャです。しかし、私はあなたのコントローラーがなぜ公開されていないのかを知りません。あなたの問題であるかもしれないし、あなたのコードがうまくいきませんでしたか?

+0

ああ、私はちょうどここにすぐに入力しました。修飾子へのアクセスにあまり注意を払っていませんでした。 – DarthVader

+0

それで、働いていないという症状は何ですか? –

+0

誰が働いていないと言いましたか?私はそれが実現可能か良いデザインかを尋ねた/ – DarthVader

1

あなたのリポジトリ内のすべての力仕事を扱う限り、これでは何も問題。ベースステートの例外をラップする/処理する必要があるかもしれません。他の車や他の何を追跡することがあり、一方のユーザーが、ユーザーとアカウントを持ってしたいことがあります。つまり - 私は実際にユーザーが独自のエンティティとのAPIを定義することができます大規模なプロジェクトのために似た何かをやっている

。それらはすべて同じ内部コントローラーを使用しますが、それぞれに独自のエンドポイントがあります。

ジェネリックを使用していないため、私たちのコードがどれほど有用かわかりません(各オブジェクトはメタデータとして管理され、JObject辞書として操作/渡されます)。私たちはやって、多分思考のための食糧を提供しています

[POST("{primaryEntity}", RouteName = "PostPrimary")] 
public async Task<HttpResponseMessage> CreatePrimary(string primaryEntity, JObject entity) 
{ 
    // first find out which params are necessary to accept the request based on the entity's mapped metadata type 
    OperationalParams paramsForRequest = GetOperationalParams(primaryEntity, DatasetOperationalEntityIntentIntentType.POST); 

    // map the passed values to the expected params and the intent that is in use 
    IDictionary<string, object> objValues = MapAndValidateProperties(paramsForRequest.EntityModel, paramsForRequest.IntentModel, entity); 

    // get the results back from the service and return the data to the client. 
    QueryResults results = await paramsForRequest.ClientService.CreatePrimaryEntity(paramsForRequest.EntityModel, objValues, entity, paramsForRequest.IntentModel); 
     return HttpResponseMessageFromQueryResults(primaryEntity, results); 

} 
+0

幸運:)は非常に複雑に見えます。私はすべてを避けるだろう:)。 – DarthVader

+1

あなたがしていることについては、はい、わずかな過度;)。ただし、上記のコードでは、各アカウントの複数のアプリを持つ複数の顧客アカウントで、1つの汎用コントローラを使用して複数のエンティティを管理することができます(実際にはアクションごとのコントローラに分割しています)。 。上記のコードを使用して、100ms以下の応答時間で何千ものクライアントをサポートできるなら、あなたはいいですね。とにかく、思考のための食糧としてそれを達成する別の方法を示すことを試みる。 – AlexGad

+0

cool :) good luck :) – DarthVader

1

EFモデルやコードファーストから生成された1が、これはあなたのシステムのためにあまりにも複雑であるようにあなたは、事前に定義されたデザイン時のクラスを持っている場合。これは、データ・エンティティ・クラスが実行時に生成される私のプロジェクトのような、あらかじめ定義されたクラスを持っていないとすばらしいことです。

私の解決策(まだ正しく実装されていない)は、すべての要求に対して汎用コントローラを選択するカスタムIHttpControllerSelectorを作成することでしたが、コントローラの記述子タイプを、

また良い出発点は、他の人が言ったように何をやってすることは間違いなく可能ですhttp://entityrepository.codeplex.com/(私はここstackoverflowの上でこのどこかを見つけた)

1

です。しかし、リポジトリーの依存関係については、依存関係注入を使用する必要があります。私の典型的なコントローラ(ApiまたはMVC)は次のようになります。

public class PatientCategoryApiController : ApiController 
{ 

    private IEntityRepository<PatientCategory, short> m_Repository; 
    public PatientCategoryApiController(IEntityRepository<PatientCategory, short> repository) 
    { 
     if (repository == null) 
      throw new ArgumentNullException("entitiesContext is null"); 

     m_Repository = repository; 
    } 
} 

これは典型的なコンストラクタ注入パターンです。 NInjectやAutofacのようなDIやコンテナのことをよく理解している必要があります。あなたがDIを知っていないなら、あなたは長い道を先にしています。しかしこれは優れたアプローチです。この本を見てください。 https://www.manning.com/books/dependency-injection-in-dot-net

関連する問題