从 ASP.NET MVC 1.0 切换到 ASP.NET MVC 2 Beta 后,我遇到了一些不同的行为。我检查了重大更改,但尚不清楚问题出在哪里。
该问题与默认模型绑定器和实现 IDataErrorInfo 的模型有关。
属性(IDataErrorInfo.Item):
public string this[string columnName]
不再为每个属性调用。我错过了什么?
从 ASP.NET MVC 1.0 切换到 ASP.NET MVC 2 Beta 后,我遇到了一些不同的行为。我检查了重大更改,但尚不清楚问题出在哪里。
该问题与默认模型绑定器和实现 IDataErrorInfo 的模型有关。
属性(IDataErrorInfo.Item):
public string this[string columnName]
不再为每个属性调用。我错过了什么?
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);
}
}
}
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));
}
}
它不使用 IDataErrorInfo this[string columnName] 属性...似乎是一个错误,因为 DefaultModelBinder 仍然使用 Error 属性。至少是不一致。
编辑
我使用了反射器,发现似乎没有使用 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>();
}
}
}
然后我用:
ModelValidatorProviders.Providers.Add(new DataErrorInfoModelPropertyValidatorProvider());
它有效:) 这只是临时解决方案。必须在最终的 MVC 2 中更正。
编辑
我还在. if (base.Metadata.Model != null)
_Validate()
DataErrorInfoPropertyModelValidator
经过一些进一步的调试工作,我相信我明白为什么在我的特殊情况下IDataErrorInfo.Item
没有被调用。以下代码在 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>();
}
}
我的模型包含一个属性,System.Nullable<int>
当模型绑定器从 HTML 帖子中绑定一个空字符串时,Metadata.Model
它等于 null,因此验证不会运行。
这与 ASP.NET MVC 1.0 根本不同,在 ASP.NET MVC 1.0 中,此方案一直触发验证器,直到调用IDataErrorInfo.Item
.
我只是没有按照预期的方式使用某些东西吗?