1


2

インターフェイス上の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はエラーで無視されますか?

  • - - - - - - - - - - - 更新 - - - - - - - - - - - **

これは偶然にも同じ問題に苦しんでいる人のためのソリューションです。

次のクラスはコントローラーを継承します。 それを継承し、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 model) where TModel : class
    {
        return TryUpdateModelDynamic(model, null, null, null, ValueProvider);
    }

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

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

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

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

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

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

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

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

    protected internal bool TryUpdateModelDynamic(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 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 model) where TModel : class
    {
        UpdateModelDynamic(model, null, null, null, ValueProvider);
    }

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

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

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

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

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

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

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

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

    protected internal void UpdateModelDynamic(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);
        }
    }

}

1 Answer


3


https://connect.microsoft.com/VisualStudio/feedback/details/483001/in-asp-net-mvc-generic-try-updatemodel-methods-ignore-subtype-properties [バグだと思うが、ASP。 NET MVCチームは同意しません]。 モデルバインディングは、モデルの静的なコンパイル時タイプを調べます。 私はそれが好きではありませんが、それはそうです。