ASP.NET MVC:パラメータにフォームのPOSTをバインドするときに密結合を避けます

StackOverflow https://stackoverflow.com/questions/1080925

質問

のは、私のようなインターフェースを持っているとしましょう

interface IThing {
   int Id { get; set; }
   string Title { get; set; }
}

また、ASP.NET MVCで私はフォームを持っている。このようなコントローラのアクションにポストます:

 [AcceptVerbs(HttpVerbs.Post)]
 public ActionResult NewThing([Bind(Exclude = "Id")] SimpleThing thing) {

    // code to validate and persist the thing can go here            
 }

ここで、のSimpleThing のぎりぎりのIThing の実装具象クラスです。

しかし、私はすべてのメソッドがインターフェイスに対処したいと思います。私はNHiberateと、独自ののIThing の実装(のは、のRealThing のそれを呼びましょう)を使用したデータのアセンブリを持っています。それは「未知の実体」について文句を言うだろうので、私はそれにSimpleThingを渡すことはできません。

誰もがこれを行うためのクリーンな方法についてのアイデアを持っていますか?私は、ファクトリクラスを使用しての線に沿って何かを考えていました。しかし、どのように私はMVCのフォームバインダーは、それを使用することになるだろう?

ありがとうございます。

役に立ちましたか?

解決 3

があり、いくつかの良い提案はここにいたと私は実際に機能するソリューションを思いつきました。しかし、私は完全に何かになってしまいました。私はちょうど私が投稿されたフォームデータのための特定のモデルを作成し、デフォルトのモデルバインダーを使用します。

はるかに簡単、それは私が私のドメインモデル(すなわち。「コメント」フィールドのような)の一部ではないデータをキャプチャすることができます。

他のヒント

カスタムモデルバインダーを使用することができます。しかし、MSDNの記事は全く役に立ちません。だから、より良い検索を利用して、より良いものを見つけることができます。利用できる記事のplanatyがあります。

私はこれには、2つの方法を思い付きました。

最初は、MVCコントローラで使用される単純なPOCOのタイプを変換するために私のNHibernateのリポジトリクラスにコードを追加することでした(のSimpleThing の)NHibernateのは、(のRealThing ):

/// <summary>
/// A NHibernate generic repository.  Provides base of common 
/// methods to retrieve and update data.
/// </summary>
/// <typeparam name="T">The base type to expose 
/// repository methods for.</typeparam>
/// <typeparam name="K">The concrete type used by NHibernate</typeparam>
public class NHRepositoryBase<T, K> 
    : IRepository<T>
    where T : class
    where K : T, new()
{
    // repository methods ...

    /// <summary>
    /// Return T item as a type of K, converting it if necessary
    /// </summary>        
    protected static K GetKnownEntity(T item) {
        if (typeof(T) != typeof(K)) {
            K knownEntity = new K();

            foreach (var prop in typeof(T).GetProperties()) { 
                object value = prop.GetValue(item, null);
                prop.SetValue(knownEntity, value, null);
            }

            return knownEntity;
        } else {

            return (K)item;
        }            
    }

だから、リポジトリ内の任意の方法は、GetKnownEntity(Tアイテム)を呼び出すことができますし、それはあなたがNHibernateのを望んでいるタイプに渡すアイテムのプロパティをコピーします。明らかにこれは少し不格好なと感じたので、私はカスタムモデルバインダーに見えます。

<時間>

第2のアプローチでは、私はこのようなカスタムモデルバインダーを作成しました

public class FactoryModelBinder<T> 
    : DefaultModelBinder 
    where T : new() 
{

    protected override object CreateModel(ControllerContext controllerContext, 
                                          ModelBindingContext bindingContext, 
                                          Type modelType) {

        return new T();                       
    }

}

そして、私はGlobal.asax.csのそれを登録しました

ModelBinders.Binders.Add(typeof(IThing), 
            new FactoryModelBinder<RealThing>());

そして、それはこのようになりますコントローラのアクションで正常に動作します:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult NewThing([Bind(Exclude = "Id")] IThing thing) {
    // code to process the thing goes here
}
<時間>

私は2番目のアプローチを好むが、私の依存性注入のもののほとんどは、コントローラクラスです。私は、Global.asax.csのすべてのこれらのModelBinderマッピングを追加する必要が好きではありません。

これは、あなたの質問にunswer dirrectされていません。

私たちは、あなたが持っている同じ問題に対処するために、わずかに異なるアプローチを使用します。当社のコントローラは、フィールドで永続エンティティのフィールドに一致するのDTOを受け入れます。その後、我々は、ユーザーの AutoMapper のデータベースに移動しますpersistenエンティティを作成します。これはunnesseseryインターフェースを排除し、公共の対面APIをロックダウン(持続性オブジェクトのフィールドの名前を変更することは、当社のクライアントコードを壊さないことを意味します)。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top