当通过了的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的使用反射创建的对象。
任何帮助表示赞赏。
安东尼
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;
}
请问您IReferenceEntity包含在性能以及干将setter方法? 我认为,如果接口有属性设置器的最后一个样本会的工作,但你必须投它得到它来编译。
Type t = {Magically Determined Type}
IReferenceEntity d = Activator.CreatorInstance(t) as IReferenceEntity;
UpdateModel(d, formCollection.ToValueProvider());
通常情况下,它不会设置一个类的属性的原因是因为它无法找到可用的公共setter方法通过反射使用。
只是一个快速的“另一件事尝试”:
UpdateModel(d as IReferenceEntity, formCollection.ToValueProvider());
不知道是否会工作,我还没有尝试过自己,但它是浮现在脑海的第一件事。
如果我得到一个机会,我以后会以默认的模型绑定代码偷看,看看那里面有什么,很明显...
文章来源: ASP.NET MVC Issue with Using Reflection Created Objects with the Default Model Binder