ASP.NET MVC - Пользовательское сообщение проверки для типов значений - PullRequest
23 голосов
/ 14 марта 2009

Когда я использую UpdateModel или TryUpdateModel, инфраструктура MVC достаточно умна, чтобы знать, пытаетесь ли вы передать нулевой тип значения (например, пользователь забывает заполнить обязательное поле дня рождения).

К сожалению, я не знаю, как переопределить сообщение по умолчанию «Требуется значение». в резюме во что-то более значимое («Пожалуйста, введите ваш день рождения»).

Должен быть способ сделать это (без написания большого количества обходного кода), но я не могу его найти. Любая помощь?

EDIT

Кроме того, я думаю, что это также будет проблемой для недействительных конверсий, например BirthDay = "Hello".

Ответы [ 7 ]

19 голосов
/ 23 апреля 2010

Создайте свой собственный 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();

Ура!

6 голосов
/ 03 сентября 2009

С помощью DefaultModelBinder можно переопределить требуемое сообщение об ошибке по умолчанию, но, к сожалению, оно будет применяться глобально, что, IMHO, делает его полностью бесполезным. Но если вы решите сделать это, вот как:

  1. Добавьте папку App_GlobalResources на сайт ASP.NET
  2. Добавить файл ресурсов с именем Messages.resx
  3. Внутри файла ресурсов объявите новый строковый ресурс с ключом PropertyValueRequired и некоторым значением
  4. В Application_Start добавить следующую строку:

    DefaultModelBinder.ResourceClassKey = "Messages";
    

Как видите, нет связи между проверяемым свойством модели и сообщением об ошибке.

В заключение, лучше написать собственную логику проверки для обработки этого сценария. Один из способов - использовать обнуляемый тип (System.Nullable ), а затем:

if (model.MyProperty == null || 
    /** Haven't tested if this condition is necessary **/ 
    !model.MyProperty.HasValue)
{
    ModelState.AddModelError("MyProperty", "MyProperty is required");
}
4 голосов
/ 06 апреля 2009

Я использую классную платформу проверки 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));

}
3 голосов
/ 12 октября 2009

как насчет этого?

[RegularExpression(@"^[a-zA-Z''-'\s]{1,40}$",
                   ErrorMessage = "Characters are not allowed.")]

Это должно позволить вам помечать свойства конкретными сообщениями об ошибках для любых валидаторов MVC, которые вы хотите использовать ...

2 голосов
/ 27 ноября 2009

В ASP.NET MVC 1 я тоже столкнулся с этой проблемой.

В моем проекте есть модель или бизнес-объект с именем "Entry", и его первичным ключом EntryId является int? тип, и значение EntryId может быть разрешено для ввода пользователями.

Таким образом, проблема в том, что когда поле пустое или равно нулю или существует какое-то целочисленное значение, пользовательские сообщения об ошибках могут отображаться хорошо, но если это некое целочисленное значение, например «а», я не найдите способ использовать настраиваемое сообщение для замены сообщения по умолчанию, например «Недопустимое значение« 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"
}  

но это делает контроллер полным, надеюсь, что есть реальное решение для его решения.

1 голос
/ 14 марта 2009

Посмотрите вверх ModelState.AddError.

0 голосов
/ 27 ноября 2009

да, есть способ, вы должны использовать System.ComponentModel.DataAnnotations в сочетании с xVal , и вы сможете установить правила проверки и сообщения (вы можете даже использовать файлы ресурсов для локализации) для каждого вашего свойства с помощью атрибутов
смотрите здесь http://blog.codeville.net/2009/01/10/xval-a-validation-framework-for-aspnet-mvc/

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...