[英]ASP.NET MVC 2 Beta - Default Model Binder
I'm experiencing some different behavior after switching from ASP.NET MVC 1.0 to ASP.NET MVC 2 Beta. 从ASP.NET MVC 1.0切换到ASP.NET MVC 2 Beta后,我遇到一些不同的行为。 I checked the breaking changes but it's not clear where the issue lies. 我检查了重大更改,但不清楚问题出在哪里。
The problem has to do with the default model binder and a model that implements IDataErrorInfo. 该问题与默认模型绑定程序和实现IDataErrorInfo的模型有关。
The property (IDataErrorInfo.Item): 属性(IDataErrorInfo.Item):
public string this[string columnName]
is no longer being called for each property. 不再为每个属性调用。 What am I missing? 我想念什么?
DefaultModelBinder in MVC 1.0: MVC 1.0中的DefaultModelBinder:
protected virtual void OnPropertyValidated(ControllerContext controllerContext, ModelBindingContext bindingContext, PropertyDescriptor propertyDescriptor, object value)
{
IDataErrorInfo model = bindingContext.Model as IDataErrorInfo;
if (model != null)
{
string str = model[propertyDescriptor.Name];
if (!string.IsNullOrEmpty(str))
{
string key = CreateSubPropertyName(bindingContext.ModelName, propertyDescriptor.Name);
bindingContext.ModelState.AddModelError(key, str);
}
}
}
DefaultModelBinder in MVC 2.0 beta: MVC 2.0 Beta中的DefaultModelBinder:
protected virtual void OnPropertyValidated(ControllerContext controllerContext, ModelBindingContext bindingContext, PropertyDescriptor propertyDescriptor, object value)
{
ModelMetadata metadata = bindingContext.PropertyMetadata[propertyDescriptor.Name];
metadata.Model = value;
string prefix = CreateSubPropertyName(bindingContext.ModelName, metadata.PropertyName);
foreach (ModelValidator validator in metadata.GetValidators(controllerContext))
{
foreach (ModelValidationResult result in validator.Validate(bindingContext.Model))
{
bindingContext.ModelState.AddModelError(CreateSubPropertyName(prefix, result.MemberName), result.Message);
}
}
if ((bindingContext.ModelState.IsValidField(prefix) && (value == null)) && !TypeHelpers.TypeAllowsNullValue(propertyDescriptor.PropertyType))
{
bindingContext.ModelState.AddModelError(prefix, GetValueRequiredResource(controllerContext));
}
}
It doesn't use IDataErrorInfo this[string columnName] property... Seems like a bug, because DefaultModelBinder still uses Error property. 它不使用IDataErrorInfo的this [string columnName]属性...似乎是一个错误,因为DefaultModelBinder仍使用Error属性。 It is inconsistency at least. 至少是不一致的。
EDIT 编辑
I used reflector and noticed that DataErrorInfoPropertyModelValidator doesn't seem to be used, so I created my own class: 我使用了反射器,并注意到似乎没有使用DataErrorInfoPropertyModelValidator,所以我创建了自己的类:
public class DataErrorInfoModelPropertyValidatorProvider : ModelValidatorProvider
{
// Methods
public override IEnumerable<ModelValidator> GetValidators(ModelMetadata metadata, ControllerContext context)
{
if (metadata == null)
{
throw new ArgumentNullException("metadata");
}
if (context == null)
{
throw new ArgumentNullException("context");
}
var validators = new List<ModelValidator>();
validators.Add(new DataErrorInfoPropertyModelValidator(metadata, context));
return validators;
}
internal sealed class DataErrorInfoPropertyModelValidator : ModelValidator
{
// Methods
public DataErrorInfoPropertyModelValidator(ModelMetadata metadata, ControllerContext controllerContext)
: base(metadata, controllerContext)
{
}
public override IEnumerable<ModelValidationResult> Validate(object container)
{
if (container != null)
{
IDataErrorInfo info = container as IDataErrorInfo;
if (info != null)
{
string str = info[Metadata.PropertyName];
if (!string.IsNullOrEmpty(str))
{
ModelValidationResult[] resultArray = new ModelValidationResult[1];
ModelValidationResult result = new ModelValidationResult();
result.Message = str;
resultArray[0] = result;
return resultArray;
}
}
}
return Enumerable.Empty<ModelValidationResult>();
}
}
}
Then I used: 然后我用了:
ModelValidatorProviders.Providers.Add(new DataErrorInfoModelPropertyValidatorProvider());
And it works:) This is just temporary solution. 它的工作原理是:)这只是临时解决方案。 Will have to be corrected in final MVC 2. 在最终的MVC 2中必须进行更正。
EDIT 编辑
I also changed if (base.Metadata.Model != null)
to if (container != null) in Validate()
method of DataErrorInfoPropertyModelValidator
. 我还将DataErrorInfoPropertyModelValidator
Validate()
方法中的if (base.Metadata.Model != null)
更改为if(container!= null)。
After some further debugging work I believe I understand why in my particular case the IDataErrorInfo.Item
isn't being called. 经过进一步的调试工作,我相信我理解为什么在我的特殊情况下未调用IDataErrorInfo.Item
。 The following code is used in the ASP.NET MVC 2 Beta to validate an IDataErrorInfo
property: 在ASP.NET MVC 2 Beta中使用以下代码来验证IDataErrorInfo
属性:
internal sealed class DataErrorInfoPropertyModelValidator : ModelValidator
{
public DataErrorInfoPropertyModelValidator(ModelMetadata metadata, ControllerContext controllerContext)
: base(metadata, controllerContext)
{
}
public override IEnumerable<ModelValidationResult> Validate(object container)
{
if (Metadata.Model != null)
{
var castContainer = container as IDataErrorInfo;
if (castContainer != null)
{
string errorMessage = castContainer[Metadata.PropertyName];
if (!String.IsNullOrEmpty(errorMessage))
{
return new[] { new ModelValidationResult { Message = errorMessage } };
}
}
}
return Enumerable.Empty<ModelValidationResult>();
}
}
My model contains a property that is System.Nullable<int>
and when the model binder binds an empty string from the HTML post, the Metadata.Model
is equal to null, thus the validation doesn't run. 我的模型包含一个System.Nullable<int>
属性,当模型绑定程序绑定HTML帖子中的空字符串时, Metadata.Model
等于null,因此验证不会运行。
This is fundamentally different from ASP.NET MVC 1.0, where this scenario fires the validator all the way through to a call to IDataErrorInfo.Item
. 这与ASP.NET MVC 1.0根本不同,在ASP.NET MVC 1.0中,此方案一直将验证程序激发到对IDataErrorInfo.Item
的调用。
Am I just not using something the way it was intended? 我是否只是没有按预期使用某种东西?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.