MVC 2的UpdateModel在接口上,应该ModelBinderAttribute被忽略? [英] MVC 2 UpdateModel on Interface, Should ModelBinderAttribute be ignored?

查看:158
本文介绍了MVC 2的UpdateModel在接口上,应该ModelBinderAttribute被忽略?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有形式从一个特定的抽象类的实例发布数据:

 公共抽象类IRestriction
{
    公共字符串名称{;组;}
    公共抽象IModelBinder GetBinder();
}

具体类型和PartialView在运行时确定:

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

适当的局部视图,然后正确呈现。

当的形式发回的类型正确地推断并激活的方法相同。

不过,我一直无法获得的UpdateModel绑定到具体实施。

我如何模型绑定到具体类型而不是接口?

事情我已经试过:

我已经设置ModelBinderAttribute在具体的类,但它被忽略。

  [ModelBinder的(typeof运算(MyCustomModelBinder))]
公共类ConcreteRestriction:IRestriction

我已经清除了所有的ModelBinders并从接口只添加粘合剂。

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

这些都不是工作。

最新最好的方式来完成我想要做什么?

时ModelBinderAttribute被错误的忽视?

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

下面是其他任何人与谁发生过这个运行同样的问题挣扎的解决方案。

下面的类继承控制器。继承它,并调用UpdateModelDynamic()/ TryUpdateModelDynamic()

 公共类DynamicTypeController:控制器
{
    内部静态布尔IsPropertyAllowed(字符串propertyName的,字符串[] includeProperties,字符串[] excludeProperties)
    {
        //我们允许一个属性如果双方在包括列表中,而不是在排除列表的约束。
        //空包括列表意味着所有属性都是允许的。
        //空排除列表​​意味着没有任何属性是不允许的。
        布尔includeProperty =(includeProperties == NULL)|| (includeProperties.Length == 0)|| includeProperties.Contains(propertyName的,StringComparer.OrdinalIgnoreCase);
        布尔excludeProperty =(excludeProperties!= NULL)及和放大器; excludeProperties.Contains(propertyName的,StringComparer.OrdinalIgnoreCase);
        返回includeProperty&放大器;&安培; !excludeProperty;
    }    受保护的内部布尔TryUpdateModelDynamic<&的TModel GT;(的TModel模型),其中的TModel:类
    {
        返回TryUpdateModelDynamic(型号,NULL,NULL,NULL,ValueProvider);
    }    受保护的内部布尔TryUpdateModelDynamic<&的TModel GT;(的TModel模型,字符串preFIX)其中的TModel:类
    {
        返回TryUpdateModelDynamic(型号,preFIX,NULL,NULL,ValueProvider);
    }    受保护的内部布尔TryUpdateModelDynamic<&的TModel GT;(的TModel模型的String [] includeProperties)其中的TModel:类
    {
        返回TryUpdateModelDynamic(模型,空,includeProperties,空,ValueProvider);
    }    受保护的内部布尔TryUpdateModelDynamic<&的TModel GT;(的TModel模型,字符串preFIX,字符串[] includeProperties)其中的TModel:类
    {
        返回TryUpdateModelDynamic(型号,preFIX,includeProperties,空,ValueProvider);
    }    受保护的内部布尔TryUpdateModelDynamic<&的TModel GT;(的TModel模型,字符串preFIX,字符串[] includeProperties,字符串[] excludeProperties)其中的TModel:类
    {
        返回TryUpdateModelDynamic(型号,preFIX,includeProperties,excludeProperties,ValueProvider);
    }    受保护的内部布尔TryUpdateModelDynamic<&的TModel GT;(的TModel模型,IValueProvider valueProvider)其中的TModel:类
    {
        返回TryUpdateModelDynamic(型号,NULL,NULL,NULL,valueProvider);
    }    受保护的内部布尔TryUpdateModelDynamic<&的TModel GT;(的TModel模型,字符串preFIX,IValueProvider valueProvider)其中的TModel:类
    {
        返回TryUpdateModelDynamic(型号,preFIX,NULL,NULL,valueProvider);
    }    受保护的内部布尔TryUpdateModelDynamic<&的TModel GT;(的TModel模型的String [] includeProperties,IValueProvider valueProvider)其中的TModel:类
    {
        返回TryUpdateModelDynamic(模型,空,includeProperties,空,valueProvider);
    }    受保护的内部布尔TryUpdateModelDynamic<&的TModel GT;(的TModel模型,字符串preFIX,字符串[] includeProperties,IValueProvider valueProvider)其中的TModel:类
    {
        返回TryUpdateModelDynamic(型号,preFIX,includeProperties,空,valueProvider);
    }    受保护的内部布尔TryUpdateModelDynamic<&的TModel GT;(的TModel模型,字符串preFIX,字符串[] includeProperties,字符串[] excludeProperties,IValueProvider valueProvider)其中的TModel:类
    {
        如果(型号== NULL)
        {
            抛出新的ArgumentNullException(模式);
        }
        如果(valueProvider == NULL)
        {
            抛出新的ArgumentNullException(valueProvider);
        }        predicate<串GT; propertyFilter = propertyName的= GT; IsPropertyAllowed(propertyName的,includeProperties,excludeProperties);
        IModelBinder粘合剂= Binders.GetBinder(model.GetType());        ModelBindingContext的BindingContext =新ModelBindingContext()
        {
            ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(()=>模型,model.GetType()),
            MODELNAME = preFIX,
            的ModelState =的ModelState,
            PropertyFilter = propertyFilter,
            ValueProvider = valueProvider
        };
        binder.BindModel(ControllerContext,BindingContext中);
        返回ModelState.IsValid;
    }
    受保护的内部空隙UpdateModelDynamic<&的TModel GT;(的TModel模型),其中的TModel:类
    {
        UpdateModelDynamic(型号,NULL,NULL,NULL,ValueProvider);
    }    受保护的内部空隙UpdateModelDynamic<&的TModel GT;(的TModel模型,字符串preFIX)其中的TModel:类
    {
        UpdateModelDynamic(型号,preFIX,NULL,NULL,ValueProvider);
    }    受保护的内部空隙UpdateModelDynamic<&的TModel GT;(的TModel模型的String [] includeProperties)其中的TModel:类
    {
        UpdateModelDynamic(模型,空,includeProperties,空,ValueProvider);
    }    受保护的内部空隙UpdateModelDynamic<&的TModel GT;(的TModel模型,字符串preFIX,字符串[] includeProperties)其中的TModel:类
    {
        UpdateModelDynamic(型号,preFIX,includeProperties,空,ValueProvider);
    }    受保护的内部空隙UpdateModelDynamic<&的TModel GT;(的TModel模型,字符串preFIX,字符串[] includeProperties,字符串[] excludeProperties)其中的TModel:类
    {
        UpdateModelDynamic(型号,preFIX,includeProperties,excludeProperties,ValueProvider);
    }    受保护的内部空隙UpdateModelDynamic<&的TModel GT;(的TModel模型,IValueProvider valueProvider)其中的TModel:类
    {
        UpdateModelDynamic(型号,NULL,NULL,NULL,valueProvider);
    }    受保护的内部空隙UpdateModelDynamic<&的TModel GT;(的TModel模型,字符串preFIX,IValueProvider valueProvider)其中的TModel:类
    {
        UpdateModelDynamic(型号,preFIX,NULL,NULL,valueProvider);
    }    受保护的内部空隙UpdateModelDynamic<&的TModel GT;(的TModel模型的String [] includeProperties,IValueProvider valueProvider)其中的TModel:类
    {
        UpdateModelDynamic(模型,空,includeProperties,空,valueProvider);
    }    受保护的内部空隙UpdateModelDynamic<&的TModel GT;(的TModel模型,字符串preFIX,字符串[] includeProperties,IValueProvider valueProvider)其中的TModel:类
    {
        UpdateModelDynamic(型号,preFIX,includeProperties,空,valueProvider);
    }    受保护的内部空隙UpdateModelDynamic<&的TModel GT;(的TModel模型,字符串preFIX,字符串[] includeProperties,字符串[] excludeProperties,IValueProvider valueProvider)其中的TModel:类
    {
        BOOL成功= TryUpdateModelDynamic(型号,preFIX,includeProperties,excludeProperties,valueProvider);
        如果(!成功)
        {
            字符串消息=的String.Format(类型的模型{0}无法更新。model.GetType()全名);
            抛出新的InvalidOperationException异常(消息);
        }
    }}


解决方案

<一个href=\"https://connect.microsoft.com/VisualStudio/feedback/details/483001/in-asp-net-mvc-generic-try-updatemodel-methods-ignore-subtype-properties\"相对=nofollow>我认为这是一个错误,但在ASP.NET MVC团队不同意。模型绑定着眼于静态,编译时模型的类型。我不喜欢它,但是这是怎么回事。

I have forms posting data from instances of a particular abstract class:

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

The concrete type and PartialView are determined at runtime:

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

The appropriate partial view is then rendered correctly.

When the form is sent back the type is inferred correctly and activated the same way.

However, I haven't been able to get UpdateModel to bind to the concrete implementation.

How do I get the Model to bind to the concrete type instead of the interface?

Things I've tried:

I've set the ModelBinderAttribute on the concrete class but it is being ignored.

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

I've cleared all the ModelBinders and added only the binder from the interface.

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

None of these is working.

Whats the best way to accomplish what I'm trying to do?

Is ModelBinderAttribute being ignored in error?

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

Here is a solution for anyone else struggling with the same issue who happens to run across this.

The following class inherits Controller. Inherit it and call 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);
        }
    }

}

解决方案

I think it's a bug, but the ASP.NET MVC team disagrees. Model binding looks at the static, compile-time type of the model. I don't like it, but that's how it is.

这篇关于MVC 2的UpdateModel在接口上,应该ModelBinderAttribute被忽略?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆