ASP.NET MVC 2 «значение» в переопределении IsValid в переданном атрибуте DataAnnotation равно нулю, когда отправлена ​​неверная дата - PullRequest
2 голосов
/ 25 апреля 2010

Это мой первый вопрос о переполнении стека. Мне нужна помощь по проблеме, с которой я столкнулся во время проекта ASP.NET MVC2, над которым я сейчас работаю. Я должен отметить, что я относительно новичок в дизайне MVC, поэтому, пожалуйста, несите мое невежество. Вот оно : У меня есть обычная форма, в которой отображаются различные сведения о человеке. Одним из них является «Дата рождения». Мой взгляд таков

<div class="form-items">
            <%: Html.Label("DateOfBirth", "Date of Birth:") %>
            <%: Html.EditorFor(m => m.DateOfBirth) %>
            <%: Html.ValidationMessageFor(m => m.DateOfBirth) %>
</div>

Я использую шаблон редактора, который нашел, чтобы правильно показывать только дату:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<System.DateTime?>"%>
<%= Html.TextBox("", (Model.HasValue ? Model.Value.ToShortDateString() : string.Empty))%>

Я использовал конструктор LinqToSql для создания своей модели из базы данных sql. Чтобы выполнить некоторую проверку, я создал частичный класс Person для расширения класса, созданного дизайнером (в том же пространстве имен):

[MetadataType(typeof(IPerson))]
public partial class Person : IPerson
{        //To create buddy class    }

public interface IPerson
{
    [Required(ErrorMessage="Please enter a name")]
    string Name { get; set; }
    [Required(ErrorMessage="Please enter a surname")]
    string Surname { get; set; }
    [Birthday]
    DateTime? DateOfBirth { get; set; }
    [Email(ErrorMessage="Please enter a valid email")]
    string Email { get; set; }
}

Я хочу убедиться, что введена правильная дата. Поэтому я создал собственный атрибут DataAnnotation для проверки даты:

public class BirthdayAttribute : ValidationAttribute
{
    private const string _errorMessage = "Please enter a valid date";

    public BirthdayAttribute() : base(_errorMessage) { }

    public override bool  IsValid(object value)
    {
        if (value == null)
        {
            return true;
        }
        DateTime temp;
        bool result = DateTime.TryParse(value.ToString(), out temp);
        return result;
    }
}

Ну, моя проблема в этом. Как только я введу неправильную дату в поле DateOfBirth, пользовательское сообщение не будет отображаться, даже если используется такой атрибут, как [Birthday (ErrorMessage = ".....")]. Отображаемое сообщение - это сообщение, возвращенное из БД, т. Е. «Значение« 32/4/1967 »недопустимо для DateOfBirth». Я попытался ввести некоторые точки останова вокруг кода и обнаружил, что «значение» в атрибуте всегда равно нулю, когда дата неверна, но всегда получает значение, если дата в правильном формате. То же самое (значение == ноль) также передается в коде, сгенерированном конструктором.

Эта штука сводит меня с ума. Пожалуйста, кто-нибудь может помочь мне разобраться с этим? Также, если кто-то может сказать мне, где именно находится точка входа из представления в базу данных. Это связано с моделью связующего? потому что я хотел точно проверить, какое значение передается, когда я нажимаю кнопку «отправить». Спасибо.

1 Ответ

1 голос
/ 25 апреля 2010

Вообще говоря, все средства проверки - это работа после значений, связанных связующим. Как вы понимаете, невозможно связать значение dateTime со строкой, такой как «asdvfvk». Таким образом, когда связыватель сталкивается с такой ошибкой, он добавляет ее в ModelState (взгляните на ModelState ["DateOfBirth"]. Errors [0] .ErrorMessage) и связывает значение по умолчанию. Значение по умолчанию для DateTime? имеет значение null, поэтому вы всегда получаете его в методе IsValid. Это нормально. Так что вы можете видеть, что проверка даты имеет смысл, если вы хотите проверить, например, больше ли она какой-либо другой даты. Если введенная строка неверна, дальнейшая проверка не имеет смысла.

Что ты можешь сделать?

Первый простой способ - вы можете исправить свое действие следующим образом

 [HttpPost]
        public ActionResult About(Person person, string dateOfBirth) {
            var birthdayAttribute = new BirthdayAttribute();
            if( !birthdayAttribute.IsValid(dateOfBirth)) {
                ModelState["DateOfBirth"].Errors.Clear();
                ModelState.AddModelError("DateOfBirth", birthdayAttribute.ErrorMessage);
            }
           .......
        }

Как видите, есть строка dateOfBirth, поэтому у связывателя нет проблем с привязкой строкового значения. Но это не сделает ваших пользователей счастливыми.

Лучший способ - убедиться, что строка будет в правильном формате с клиентским Javascript. На самом деле люди используют средства выбора даты для дат и чувствуют себя хорошо.

Кроме того, посмотрите здесь http://forums.asp.net/t/1512140.aspx Особенно ответ Брэда Уилсона.

...