ASP.NET MVC 2 "значение" в переопределении IsValid в переданном атрибуте DataAnnotation равно нулю, когда отправляется неверная дата

Это мой первый вопрос о переполнении стека. Мне нужна помощь по проблеме, с которой я столкнулся во время проекта 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". Я попытался ввести некоторые точки останова вокруг кода и обнаружил, что "значение" в атрибуте всегда равно нулю, когда дата неверна, но всегда получает значение, если дата в правильном формате. То же самое (значение == null) также передается в коде, сгенерированном дизайнером.

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

1 ответ

Решение

Вообще говоря, все средства проверки - это работа после значений, связанных связующим. Как вы понимаете, невозможно связать значение 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 Ответ Especialy Брэда Уилсона.

Другие вопросы по тегам