2012-02-21 8 views
2

コアライブラリによって参照されていないが、Webアプリケーションから参照されているアセンブリ内の型があります。例えばモデルバインディング - 外部アセンブリを入力

namespace MyApp.Models { 
    public class LatestPosts { 
     public int NumPosts { get; set; } 
    } 
} 

は、今私は、コアライブラリに次のコードを持っている:

[HttpPost, ValidateAntiForgeryToken] 
public ActionResult NewWidget(FormCollection collection) { 
    var activator = Activator.CreateInstance("AssemblyName", "MyApp.Models.LatestPosts"); 
    var latestPosts = activator.Unwrap(); 

    // Try and update the model 
    TryUpdateModel(latestPosts); 
} 

コードはかなり自明ですが、latestPosts.NumPostsプロパティの値は、フォームのコレクション内に存在するにもかかわらず、更新されません。

誰かがこれがうまくいかない理由と代替方法があるかどうかを説明することができたら、私は感謝します。

おかげ

答えて

3

あなたの問題は、型が別のアセンブリにしたり、動的にActivator.Createでそれを作成しているということであるという事実とは関係ありません。次のコードは、はるかに簡単な方法で問題を示す:

[HttpPost, ValidateAntiForgeryToken] 
public ActionResult NewWidget(FormCollection collection) 
{ 
    // notice the type of the latestPosts variable -> object 
    object latestPosts = new MyApp.Models.LatestPosts(); 

    TryUpdateModel(latestPosts); 

    // latestPosts.NumPosts = 0 at this stage no matter whether you had a parameter 
    // called NumPosts in your request with a different value or not 
    ... 
} 

問題が理由で閉じController.TryUpdateModel<TModel>this connect issueで説明したようにモデルタイプを決定するためにtypeof(TModel)代わりにmodel.GetType()を使用するという事実(由来:by design )。

回避策は、あなたが期待するように動作しますカスタムTryUpdateModel方法ロールです:その後、

protected internal bool MyTryUpdateModel<TModel>(TModel model, string prefix, string[] includeProperties, string[] excludeProperties, IValueProvider valueProvider) where TModel : class 
{ 
    if (model == null) 
    { 
     throw new ArgumentNullException("model"); 
    } 
    if (valueProvider == null) 
    { 
     throw new ArgumentNullException("valueProvider"); 
    } 

    Predicate<string> propertyFilter = propertyName => new BindAttribute().IsPropertyAllowed(propertyName); 
    IModelBinder binder = Binders.GetBinder(typeof(TModel)); 

    ModelBindingContext bindingContext = new ModelBindingContext() 
    { 
     // in the original method you have: 
     // ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => model, typeof(TModel)), 
     ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => model, model.GetType()), 
     ModelName = prefix, 
     ModelState = ModelState, 
     PropertyFilter = propertyFilter, 
     ValueProvider = valueProvider 
    }; 
    binder.BindModel(ControllerContext, bindingContext); 
    return ModelState.IsValid; 
} 

をして:

[HttpPost, ValidateAntiForgeryToken] 
public ActionResult NewWidget(FormCollection collection) 
{ 
    object latestPosts = new MyApp.Models.LatestPosts(); 

    MyTryUpdateModel(latestPosts, null, null, null, ValueProvider); 

    // latestPosts.NumPosts will be correctly bound now 
    ... 
} 
+0

おかげで御馳走を働きました! – nfplee

+0

ああ、ありがとう! – Rookian

+0

このようないくつかのソリューションに直面するとき、私は本当の良いプログラマであることから遠く離れていることを認識しています。この問題はある日失われました。どうもありがとうございました。 – Alexandre

関連する問題