ASP.NET MVC - Пользовательское сообщение проверки для типов значений
Когда я использую UpdateModel или TryUpdateModel, среда MVC достаточно умна, чтобы знать, пытаетесь ли вы передать нуль в тип значения (например, пользователь забывает заполнить требуемое поле "День рождения" ).
К сожалению, я не знаю, как переопределить сообщение по умолчанию: "Требуется значение". в резюме в нечто более значимое ( "Пожалуйста, введите в свой день рождения" ).
Должен быть способ сделать это (без написания слишком много кода для работы), но я не могу его найти. Любая помощь?
ИЗМЕНИТЬ
Кроме того, я предполагаю, что это также будет проблемой для неверных преобразований, например. BirthDay = "Hello".
Ответы
Ответ 1
Создайте свой собственный ModelBinder, расширив DefaultModelBinder:
public class LocalizationModelBinder : DefaultModelBinder
Переопределить SetProperty:
base.SetProperty(controllerContext, bindingContext, propertyDescriptor, value);
foreach (var error in bindingContext.ModelState[propertyDescriptor.Name].Errors.
Where(e => IsFormatException(e.Exception)))
{
if (propertyDescriptor.Attributes[typeof(TypeErrorMessageAttribute)] != null)
{
string errorMessage =
((TypeErrorMessageAttribute)propertyDescriptor.Attributes[typeof(TypeErrorMessageAttribute)]).GetErrorMessage();
bindingContext.ModelState[propertyDescriptor.Name].Errors.Remove(error);
bindingContext.ModelState[propertyDescriptor.Name].Errors.Add(errorMessage);
break;
}
}
Добавьте функцию bool IsFormatException(Exception e)
, чтобы проверить, является ли исключение исключением FormatException:
if (e == null)
return false;
else if (e is FormatException)
return true;
else
return IsFormatException(e.InnerException);
Создать класс атрибута:
[AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = false)]
public class TypeErrorMessageAttribute : Attribute
{
public string ErrorMessage { get; set; }
public string ErrorMessageResourceName { get; set; }
public Type ErrorMessageResourceType { get; set; }
public TypeErrorMessageAttribute()
{
}
public string GetErrorMessage()
{
PropertyInfo prop = ErrorMessageResourceType.GetProperty(ErrorMessageResourceName);
return prop.GetValue(null, null).ToString();
}
}
Добавьте атрибут к свойству, которое вы хотите проверить:
[TypeErrorMessage(ErrorMessageResourceName = "IsGoodType", ErrorMessageResourceType = typeof(AddLang))]
public bool IsGood { get; set; }
AddLang - это файл resx, а IsGoodType - это имя ресурса.
И, наконец, добавьте это в Global.asax.cs Application_Start:
ModelBinders.Binders.DefaultBinder = new LocalizationModelBinder();
Ура!
Ответ 2
В DefaultModelBinder можно переопределить требуемое по умолчанию сообщение об ошибке, но, к сожалению, оно применимо во всем мире, которое ИМХО делает его совершенно бесполезным. Но в случае, если вы решили сделать это здесь, как:
Как вы видите, нет никакой связи между проверяемой моделью и сообщением об ошибке.
В заключение лучше написать специальную логику проверки для обработки этого сценария. Один из способов - использовать тип с нулевым значением (System.Nullable <TValueType> ), а затем:
if (model.MyProperty == null ||
/** Haven't tested if this condition is necessary **/
!model.MyProperty.HasValue)
{
ModelState.AddModelError("MyProperty", "MyProperty is required");
}
Ответ 3
Я использую awesome xVal рамки проверки. Это позволяет мне выполнять всю мою проверку в модели (даже LINQ-SQL:)). Он также испускает javascript, необходимый для проверки на стороне клиента.
РЕДАКТИРОВАТЬ: Извините за ссылка за то, как заставить его работать для LINQ-SQL
Основной рабочий процесс выглядит примерно так.
public partial class YourClass
{
[Required(ErrorMessage = "Property is required.")]
[StringLength(200)]
public string SomeProperty{ get; set; }
}
try
{
// Validate the instance of your object
var obj = new YourClass() { SomeProperty = "" }
var errors = DataAnnotationsValidationRunner.GetErrors(obj);
// Do some more stuff e.g. Insert into database
}
catch (RulesException ex)
{
// e.g. control name 'Prefix.Title'
ex.AddModelStateErrors(ModelState, "Prefix");
ModelState.SetModelValue("Prefix.Title", new ValueProviderResult(ValueProvider["Prefix.Title"].AttemptedValue, collection["Prefix.Title"], System.Globalization.CultureInfo.CurrentCulture));
}
Ответ 4
как насчет этого?
[RegularExpression(@"^[a-zA-Z''-'\s]{1,40}$",
ErrorMessage = "Characters are not allowed.")]
Это должно позволить вам отмечать свойства с конкретными сообщениями об ошибках для любых валидаторов MVC, которые вы хотите использовать...
Ответ 5
Посмотрите ModelState.AddError
.
Ответ 6
В ASP.NET MVC 1 я тоже встретил эту проблему.
В моем проекте есть модель или бизнес-объект с именем "Enter", а его первичный ключ EntryId - int? тип, а значение EntryId может быть разрешено вводить пользователями.
Таким образом, проблема заключается в том, что, когда поле пустое или нулевое или какое-то целочисленное значение, которое существует, пользовательские сообщения об ошибках могут быть хорошо отображены, но если значение представляет собой некоторое нецелое значение типа "a", я не могу найти способ использования настраиваемого сообщения для замены сообщения по умолчанию, например "Значение" a "недействительно".
когда я отслеживаю сообщение об ошибке в ModelState, я обнаружил, что если значение не целое, будут две ошибки, связанные с EntryId, а сообщение об ошибке первого элемента пустое...
Теперь я должен использовать такой уродливый код, чтобы взломать проблему.
if (ModelState["EntryId"].Errors.Count > 1)
{
ModelState["EntryId"].Errors.Clear(); //should not use ModelState["EntryId"].remove();
ModelState.AddModelError("EntryId", "必须为大于0的整数"); //必须为大于0的整数 means "it should be an integer value and great than 0"
}
но это делает контрольный жир, надеюсь, что существует реальное решение для его решения.
Ответ 7
да, есть способ, вы должны использовать System.ComponentModel.DataAnnotations в комбинации с xVal, и вы сможете установить правила и сообщения для проверки ( u может даже использовать файлы ресурсов для локализации) для каждого вашего свойства, используя атрибуты
смотрите здесь http://blog.codeville.net/2009/01/10/xval-a-validation-framework-for-aspnet-mvc/