Значение ValidationAttribute всегда пустое - PullRequest
1 голос
/ 01 декабря 2010

Вот простой проверочный атрибут, который я написал для обеспечения использования строк, состоящих только из цифр (я использую его для проверки телефонных номеров, почтовых индексов и т. Д.):

public class NumericAttribute : ValidationAttribute {

    public NumericAttribute() {
        ErrorMessage = SharedModelResources.ValidationStrings.Numeric; // Message coming from a .resx file
    }

    public override bool IsValid(object value) {

        string stringValue = value as string;

        if (stringValue.IsNotNull())
            foreach (var c in stringValue)
                if (!char.IsDigit(c))
                    return false;

        return true;
    }

}

Проблема в том, что при проверке, отличной от строк, скажем, десятичной, короткой, целой или любой другой, object value ВСЕГДА null. Зачем проверять только цифры? Потому что, если я этого не сделаю, я получу сообщение проверки по умолчанию «Значение« x »недопустимо для« propertyName ». Мне известно о решениях для конкретной проблемы сообщения проверки по умолчанию.

Я просто хочу понять, ПОЧЕМУ оно всегда равно нулю ...

Кстати, я использую VS2008, ASP.NET MVC 2 (финальная версия), .NET 3.5 SP1.

Ответы [ 4 ]

1 голос
/ 01 декабря 2010

Хорошо, спасибо @mcl за предложение отладки до конца (View> Controller> Model) до атрибута проверки!

Вот что произошло: при вставке неверного ввода в текстовое поле, привязанное к чему-либо, что не являетсяСтрока в модели, «DefaultModelBinder» устанавливает значение «null» до того, как достигнет даже контроллера!(У кого-нибудь есть дополнительная информация по этому поводу? Я был бы рад!)

1 голос
/ 01 декабря 2010

Если ваш сценарий заключается в том, что вы пытаетесь прикрепить свой валидатор к свойству типа int, десятичное и т. Д., и , то значение, которое входит, не преобразуется в int, десятичное и т. Д. , то это намеренно.

Подумайте, что вы просите сделать MVC-фреймворк. Свойство имеет тип int, поэтому инфраструктура MVC работает со значениями типа int. (Технически, он работает с чем-то более похожим на Nullable .) Если входящее значение не может быть преобразовано в int, невозможно представить его в Nullable , отличном от null , так как Тип не может содержать произвольные строки. Вот почему ваш атрибут проверки в итоге получает null в качестве значения.

Изменить:

Если вы хотите управлять этим сообщением об ошибке, самый простой вариант - изменить свойство на строку, а затем попросить ваш пользовательский валидатор вызвать Int32.TryParse или выполнить все, что вам нужно, чтобы убедиться, что введенный пользователем текст числовой. Тогда у вас может быть отдельное свойство только для чтения, которое в основном представляет собой числовую форму значения этого свойства.

Более сложный, но более обобщенный, вы можете заменить встроенный DefaultModelBinder одним из ваших собственных созданий. В методе BindModel найдите исключения типа FormatException в ModelState, а затем замените их выбранным сообщением об ошибке. См. Конец метода DefaultModelBinder.BindProperty для примера того, как это делается.

1 голос
/ 01 декабря 2010

Вы уверены, что это value, что является нулевым, а не просто stringValue?

Так скажите MSDN о вашем as операторе:

Оператор asпохож на приведение, за исключением того, что он возвращает ноль при сбое преобразования вместо вызова исключения.

http://msdn.microsoft.com/en-us/library/cscsdfbt%28VS.71%29.aspx

В примерах на этой странице показано, что числовые значения не as для струнных, как вы хотите.

Вместо этого вы можете попробовать .ToString().

0 голосов
/ 28 апреля 2012

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

    private DateTime _dt;

    [LocalizedValidDateAttribute("Resources.DateTimeOffsetModel.App_GlobalResources", "TimePart_Invalid")]   
    public string DateTimeString
    {
        get { return _dt.ToString(); }
        set { DateTime.TryParse(value, out _dt); }
    }    

Если вы передадите DateTimeString = "foobar"; Когда LocalizedValidDateAttribute.IsValid () сработает, он попытается получить значение DateTimeString, которое будет нулевым, поскольку «foobar» не является строкой.

Надеюсь, это поможет кому-то еще сэкономить 2 часа, которые понадобились мне, чтобы понять это.

...