Причина, по которой это происходит, заключается в том, что механизм связывания модели (который запускается до любых валидаторов) не может связать недопустимое значение с целым числом.Вот почему внутри вашего валидатора вы не получите никакой ценности.Если вы хотите проверить это, вы можете написать пользовательское связующее для модели целочисленного типа.
Вот как может выглядеть такое связующее для модели:
public class IntegerBinder : IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
int temp;
if (value == null ||
string.IsNullOrEmpty(value.AttemptedValue) ||
!int.TryParse(value.AttemptedValue, out temp)
)
{
bindingContext.ModelState.AddModelError(bindingContext.ModelName, "invalid integer");
bindingContext.ModelState.SetModelValue(bindingContext.ModelName, value);
return null;
}
return temp;
}
}
, и вы зарегистрируете егов Application_Start
:
ModelBinders.Binders.Add(typeof(int), new IntegerBinder());
Но вы можете спросить: а что если я захочу настроить сообщение об ошибке?В конце концов, это то, чего я пытался достичь в первую очередь.Какой смысл писать эту модель связки, когда стандартная уже делает это для меня, просто я не могу настроить сообщение об ошибке?
Ну, это довольно просто.Вы можете создать пользовательский атрибут, который будет использоваться для украшения вашей модели вида и который будет содержать сообщение об ошибке, а внутри подшивки модели вы сможете получить это сообщение об ошибке и использовать его вместо этого.
Итак,у вас может быть фиктивный атрибут валидатора:
public class MustBeAValidInteger : ValidationAttribute, IMetadataAware
{
public override bool IsValid(object value)
{
return true;
}
public void OnMetadataCreated(ModelMetadata metadata)
{
metadata.AdditionalValues["errorMessage"] = ErrorMessage;
}
}
, который вы можете использовать для украшения вашей модели вида:
[MustBeAValidInteger(ErrorMessage = "The value {0} is not a valid quantity")]
public int Quantity { get; set; }
и адаптировать подшивку модели:
public class IntegerBinder : IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
int temp;
var attemptedValue = value != null ? value.AttemptedValue : string.Empty;
if (!int.TryParse(attemptedValue, out temp)
)
{
var errorMessage = "{0} is an invalid integer";
if (bindingContext.ModelMetadata.AdditionalValues.ContainsKey("errorMessage"))
{
errorMessage = bindingContext.ModelMetadata.AdditionalValues["errorMessage"] as string;
}
errorMessage = string.Format(errorMessage, attemptedValue);
bindingContext.ModelState.AddModelError(bindingContext.ModelName, errorMessage);
bindingContext.ModelState.SetModelValue(bindingContext.ModelName, value);
return null;
}
return temp;
}
}