The "ASP.NET MVC 2" value in the IsValid override in the passed DataAnnotation attribute is NULL when an invalid date is sent

This is my first question here about Stack Overflow. I need help with a problem I ran into during an ASP.NET MVC2 project that I am currently working on. I must point out that I am relatively new to MVC design, so pls bear my ignorance. Here it is: I have a regular form that shows various details about a person. One of them is "Date of birth". My view looks like this

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

      

I'm using the editor template I found to display only the date correctly:

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

      

I have used LinqToSql constructor to create my model from sql database. To do some validation, I made a partial Person class to extend the one generated by the constructor (in the same namespace):

[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; }
}

      

I want the correct date to be entered. So I created my own DataAnnotation attribute for date validation:

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;
    }
}

      

Okay, this is my problem. As soon as I enter an incorrect date in the DateOfBirth field, the custom message will not be displayed, even if an attribute of type [Birthday (ErrorMessage = ".....")] is used. The message displayed is the one that is returned from the db i.e. "The value '32/4/1967' is not valid for DateOfBirth.". I tried to introduce some breakpoints around the code and found out that the "value" in the attribute is always null when the date is incorrect, but always gets a value if the date is in the correct format. The same (value == null) is passed also in the code generated by the constructor.

This thing turns me on. Please help me deal with this? Also if someone can tell me where exactly is the entry point from the view to the database. Is this related to the model binder? because I wanted to check exactly what value is being passed when I click the submit button. Thanks.

+2


a source to share


1 answer


Generally speaking, all validation stuff is work after the bound bindings. As you can imagine, it is not possible to associate a dateTime value with a string like "asdvfvk". Thus, when the binder encounters such an error, it adds it to the ModelState (see ModelState ["DateOfBirth"]. Errors [0] .ErrorMessage) and binds the default. Default value for DateTime? is null, so you always get it in the IsValid method. This is normal. Since you can see that checking for a date makes sense if you want to check, for example, if it is greater than some other date. If the input line is incorrect, there is no further verification.

What can you do?

The first easy way - you can correct your action as follows

 [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);
            }
           .......
        }

      



As you can see there is a dateOfBirth string, so the binder has no problem with the string binding value. But that won't make your users happy.

The best way is to make sure the string is in the correct format with a Javascript client. In fact, people use date pickers for dates and feel good about it.

Also, take a look here http://forums.asp.net/t/1512140.aspx Brad Wilson's specific answer.

+1


a source







All Articles