ASP.NET MVC问题与使用反射创建的对象与默认模型绑定(ASP.NET MVC Issue w

2019-10-17 16:41发布

当通过了的FormCollection我有在ASP.NET MVC与对象不具有的UpdateModel更新一个奇怪的问题。 的UpdateModel不会出现通过反射创建要更新的对象时工作正常。

情形:我有具有大约50的查找表的应用程序 - 其每一个包括完全相同的架构包括像ID,标题,描述,isactive和createdon典型字段。 而不是建立50次,我想有可能从所有的查找表的显示数据的单一视图。 我创建了一个名为IReferenceEntity的接口,并在每个波苏斯代表我的查找表来实现它。

使用这个接口,我能够很容易地填充从查找表中记录的视图。 (I项目传递给通过以下的图。)

System.Web.Mvc.ViewPage<MyNamespece.IReferenceEntity> 

从数据库的观点,每一件事情完美的作品。

然而,当我尝试更新后的模型,我遇到了一些问题。

如果我明确地声明如下所示的对象引用,每一件事情完美的作品和我的对象的值从我的表单中的值更新。 因此,我就可以更新数据库。

AccountStatus a = new AccountStatus();

UpdateModel(a, formCollection.ToValueProvider());

不幸的是,硬编码的对象类型将彻底击垮了使用界面的原因。

(应用程序的主要目的是要能够动态地添加新的表,例如查找表,而无需做任何事情的“特殊”。这是通过反射在加载组件和定位,其实现特定接口或基类的任何类来实现)

我的策略是,以确定具体的类型对象在回传,然后通过反射创建类型的实例。 (I用来确定类型是有些原始的机制。我包括它作为模内的隐藏字段。更好的想法是受欢迎的。)

当我通过下列任一方法的创建使用反射的对象的一个​​实例,没有任何对象都被的UpdateModel更新。

Type t = {Magically Determined Type}

object b = Activator.CreatorInstance(t);

UpdateModel(b, formCollection.ToValueProvider());


Type t = {Magically Determined Type}

var c = Activator.CreatorInstance(t);

UpdateModel(c, formCollection.ToValueProvider());


Type t = {Magically Determined Type}

IReferenceEntity d = Activator.CreatorInstance(t);

UpdateModel(d, formCollection.ToValueProvider());

注:我已经验证其正在通过云南财贸所创建的对象都是正确的类型。

有没有人有任何想法,为什么这可能发生? 我有些为难。

如果我是真的“硬起来”,我可以创建工厂对象这将许多实例,这些参考实体/查找对象中的任何一个。 然而,这将打破应用程序的能力,可允许添加和透明地发现新的查找表,只是不是很干净。

另外,我可以尝试从,而不是一个接口的实际ReferenceEntity基类派生的,但我怀疑这将使任何区别。 这个问题似乎是在ModelBinder的使用反射创建的对象。

任何帮助表示赞赏。

安东尼

Answer 1:

AUGI回答了这个在ASP.NET论坛。 它曾与一对夫妇只稍作修改的。 谢谢AUGI。


问题是,[尝试]的UpdateModel方法允许使用通用参数指定型号类型只有这样,他们不允许动态模型类型规范。 我创建了问题票这一点。

你可以在这里看到TryModelUpdate方法实现。 因此,这并不难写自己的过载:

public virtual bool TryUpdateModelDynamic<TModel>(TModel model, string prefix, string[] includeProperties, string[] excludeProperties, IDictionary<string, ValueProviderResult> valueProvider) where TModel : class
{
    if (model == null)
    {
        throw new ArgumentNullException("model");
    }
    if (valueProvider == null)
    {
        throw new ArgumentNullException("valueProvider");
    }


    //Predicate<string> propertyFilter = propertyName => BindAttribute.IsPropertyAllowed(propertyName, includeProperties, excludeProperties);  
    IModelBinder binder = Binders.GetBinder( /*typeof(TModel)*/model.GetType());

    ModelBindingContext bindingContext = new ModelBindingContext()
                                             {
                                                 Model = model,
                                                 ModelName = prefix,
                                                 ModelState = ModelState,
                                                 //ModelType = typeof(TModel), // old  
                                                 ModelType = model.GetType(),
                                                 // new  
                                                 //PropertyFilter = propertyFilter,  
                                                 ValueProvider = valueProvider
                                             };
    binder.BindModel(ControllerContext, bindingContext);
    return ModelState.IsValid;
}


Answer 2:

请问您IReferenceEntity包含在性能以及干将setter方法? 我认为,如果接口有属性设置器的最后一个样本会的工作,但你必须投它得到它来编译。

Type t = {Magically Determined Type}

IReferenceEntity d = Activator.CreatorInstance(t) as IReferenceEntity;

UpdateModel(d, formCollection.ToValueProvider());

通常情况下,它不会设置一个类的属性的原因是因为它无法找到可用的公共setter方法通过反射使用。



Answer 3:

只是一个快速的“另一件事尝试”:

UpdateModel(d as IReferenceEntity, formCollection.ToValueProvider());

不知道是否会工作,我还没有尝试过自己,但它是浮现在脑海的第一件事。

如果我得到一个机会,我以后会以默认的模型绑定代码偷看,看看那里面有什么,很明显...



文章来源: ASP.NET MVC Issue with Using Reflection Created Objects with the Default Model Binder