2010-07-15 18 views
1

我有形成從一個特定的抽象類的實例發佈數據:接口上的MVC 2 UpdateModel,應該忽略ModelBinderAttribute?

public abstract class IRestriction 
{ 
    public string Name {get; set;} 
    public abstract IModelBinder GetBinder(); 
} 

具體類型和PartialView在運行時確定:

IRestriction restriction = (IRestriction)Activator.CreateInstance(Type.GetType(restriction.restriction_class)); 

適當局部視圖然後正確呈現。

當表單被髮回時,類型被正確地推斷並以相同的方式被激活。

但是,我一直無法獲得UpdateModel綁定到具體的實現。

如何讓模型綁定到具體類型而不是界面?

事情我已經嘗試:

我已經設置了ModelBinderAttribute在具體的類,但它被忽略。

[ModelBinder(typeof(MyCustomModelBinder))] 
public class ConcreteRestriction : IRestriction 

我已經清除了所有ModelBinder,並且只添加了界面上的活頁夾。

Binders.Clear(); 
Binders.Add(item.GetType(), item.GetBinder()); 

這些都不起作用。

什麼是最好的方式來完成我想要做的?

ModelBinderAttribute在錯誤中被忽略?

** ---------------------- UPDATE --------------------- - **

這是一個解決方案,可以幫助其他任何人解決同樣的問題,並且碰巧碰到這個問題。

以下類繼承Controller。繼承它,並調用UpdateModelDynamic()/ TryUpdateModelDynamic()

public class DynamicTypeController : Controller 
{ 
    internal static bool IsPropertyAllowed(string propertyName, string[] includeProperties, string[] excludeProperties) 
    { 
     // We allow a property to be bound if its both in the include list AND not in the exclude list. 
     // An empty include list implies all properties are allowed. 
     // An empty exclude list implies no properties are disallowed. 
     bool includeProperty = (includeProperties == null) || (includeProperties.Length == 0) || includeProperties.Contains(propertyName, StringComparer.OrdinalIgnoreCase); 
     bool excludeProperty = (excludeProperties != null) && excludeProperties.Contains(propertyName, StringComparer.OrdinalIgnoreCase); 
     return includeProperty && !excludeProperty; 
    } 

    protected internal bool TryUpdateModelDynamic<TModel>(TModel model) where TModel : class 
    { 
     return TryUpdateModelDynamic(model, null, null, null, ValueProvider); 
    } 

    protected internal bool TryUpdateModelDynamic<TModel>(TModel model, string prefix) where TModel : class 
    { 
     return TryUpdateModelDynamic(model, prefix, null, null, ValueProvider); 
    } 

    protected internal bool TryUpdateModelDynamic<TModel>(TModel model, string[] includeProperties) where TModel : class 
    { 
     return TryUpdateModelDynamic(model, null, includeProperties, null, ValueProvider); 
    } 

    protected internal bool TryUpdateModelDynamic<TModel>(TModel model, string prefix, string[] includeProperties) where TModel : class 
    { 
     return TryUpdateModelDynamic(model, prefix, includeProperties, null, ValueProvider); 
    } 

    protected internal bool TryUpdateModelDynamic<TModel>(TModel model, string prefix, string[] includeProperties, string[] excludeProperties) where TModel : class 
    { 
     return TryUpdateModelDynamic(model, prefix, includeProperties, excludeProperties, ValueProvider); 
    } 

    protected internal bool TryUpdateModelDynamic<TModel>(TModel model, IValueProvider valueProvider) where TModel : class 
    { 
     return TryUpdateModelDynamic(model, null, null, null, valueProvider); 
    } 

    protected internal bool TryUpdateModelDynamic<TModel>(TModel model, string prefix, IValueProvider valueProvider) where TModel : class 
    { 
     return TryUpdateModelDynamic(model, prefix, null, null, valueProvider); 
    } 

    protected internal bool TryUpdateModelDynamic<TModel>(TModel model, string[] includeProperties, IValueProvider valueProvider) where TModel : class 
    { 
     return TryUpdateModelDynamic(model, null, includeProperties, null, valueProvider); 
    } 

    protected internal bool TryUpdateModelDynamic<TModel>(TModel model, string prefix, string[] includeProperties, IValueProvider valueProvider) where TModel : class 
    { 
     return TryUpdateModelDynamic(model, prefix, includeProperties, null, valueProvider); 
    } 

    protected internal bool TryUpdateModelDynamic<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 => IsPropertyAllowed(propertyName, includeProperties, excludeProperties); 
     IModelBinder binder = Binders.GetBinder(model.GetType()); 

     ModelBindingContext bindingContext = new ModelBindingContext() 
     { 
      ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => model, model.GetType()), 
      ModelName = prefix, 
      ModelState = ModelState, 
      PropertyFilter = propertyFilter, 
      ValueProvider = valueProvider 
     }; 
     binder.BindModel(ControllerContext, bindingContext); 
     return ModelState.IsValid; 
    } 


    protected internal void UpdateModelDynamic<TModel>(TModel model) where TModel : class 
    { 
     UpdateModelDynamic(model, null, null, null, ValueProvider); 
    } 

    protected internal void UpdateModelDynamic<TModel>(TModel model, string prefix) where TModel : class 
    { 
     UpdateModelDynamic(model, prefix, null, null, ValueProvider); 
    } 

    protected internal void UpdateModelDynamic<TModel>(TModel model, string[] includeProperties) where TModel : class 
    { 
     UpdateModelDynamic(model, null, includeProperties, null, ValueProvider); 
    } 

    protected internal void UpdateModelDynamic<TModel>(TModel model, string prefix, string[] includeProperties) where TModel : class 
    { 
     UpdateModelDynamic(model, prefix, includeProperties, null, ValueProvider); 
    } 

    protected internal void UpdateModelDynamic<TModel>(TModel model, string prefix, string[] includeProperties, string[] excludeProperties) where TModel : class 
    { 
     UpdateModelDynamic(model, prefix, includeProperties, excludeProperties, ValueProvider); 
    } 

    protected internal void UpdateModelDynamic<TModel>(TModel model, IValueProvider valueProvider) where TModel : class 
    { 
     UpdateModelDynamic(model, null, null, null, valueProvider); 
    } 

    protected internal void UpdateModelDynamic<TModel>(TModel model, string prefix, IValueProvider valueProvider) where TModel : class 
    { 
     UpdateModelDynamic(model, prefix, null, null, valueProvider); 
    } 

    protected internal void UpdateModelDynamic<TModel>(TModel model, string[] includeProperties, IValueProvider valueProvider) where TModel : class 
    { 
     UpdateModelDynamic(model, null, includeProperties, null, valueProvider); 
    } 

    protected internal void UpdateModelDynamic<TModel>(TModel model, string prefix, string[] includeProperties, IValueProvider valueProvider) where TModel : class 
    { 
     UpdateModelDynamic(model, prefix, includeProperties, null, valueProvider); 
    } 

    protected internal void UpdateModelDynamic<TModel>(TModel model, string prefix, string[] includeProperties, string[] excludeProperties, IValueProvider valueProvider) where TModel : class 
    { 
     bool success = TryUpdateModelDynamic(model, prefix, includeProperties, excludeProperties, valueProvider); 
     if (!success) 
     { 
      string message = String.Format("The model of type '{0}' could not be updated.", model.GetType().FullName); 
      throw new InvalidOperationException(message); 
     } 
    } 

} 

回答

3

I think it's a bug, but the ASP.NET MVC team disagrees。模型綁定查看模型的靜態編譯時類型。我不喜歡它,但事情就是這樣。

+0

geez ...你會認爲他們至少會選擇提供自己的類型! – 2010-07-15 17:37:41

+1

我正在尋找來源,你是正確的。 不確定推理是什麼,因爲看起來所有的ValidateModel邏輯都使用.GetType()代替typeof()。 現在我重寫了所有這一切,以便我可以切換該語句。 謝謝! – jwsample 2010-07-15 17:52:09

+0

我用我如何解決這個問題更新了文本。希望它可以幫助別人。 – jwsample 2010-07-15 19:22:11