0

I have a custom data annotation validator to validate the date of birth to be between 150 years from today.

Here is my custom data annotation:

public class DateOfBirthRange : RangeAttribute
{
    public DateOfBirthRange()
        : base(typeof(DateTime), DateTime.Now.AddYears(-150).ToShortDateString(), DateTime.Now.ToShortDateString()) { }
}

Using it like this:

[Required(ErrorMessage = "BirthDate is required.")]
[DisplayName("Birth Date")]
[DateOfBirthRange(ErrorMessage = "BirthDate must be between {1:M/d/yyyy} and {2:M/d/yyyy}")]
public DateTime BirthDate { get; set; }

This is a very strange problem because the error that I'm getting back has nothing to do with the data annotation. Its causing an error in my view here:

<%: Html.DropDownListFor(m => m.JuniorSenior, (IEnumerable<SelectListItem>)ViewData["seniority"], new { @class = "input-small" })%>

ERROR: The ViewData item that has the key 'JuniorSenior' is of type 'System.String' but must be of type 'IEnumerable'.

That error is strange because that part of the code is working perfectly fine. What also makes this strange is that this error only occurs when the date entered is before 150 years from today. So that error only occurs when the date of birth validation fails. As I was debugging, I noticed that once I remove the custom data annotation, everything works fine and no error is encountered.

So that leads me to assume the problem is in my data annotation.

Here is my controller code in case you want to see what I'm trying to do.

[HttpPost]
        public ActionResult Save(PatientModel patModel, FormCollection values)
        {
            // remove white space form text box fields
            patModel.FirstName = values["FirstName"].Trim();
            patModel.LastName = values["LastName"].Trim();
            patModel.Initials = values["Initials"].Trim();
            patModel.StreetAddress1 = values["StreetAddress1"].Trim();
            patModel.StreetAddress2 = values["StreetAddress2"].Trim();
            patModel.PostalCode = values["PostalCode"].Trim();

            if (ModelState.IsValid)
            {
                try
                {
                    // Pull the long form of the gender into the model.
                    if (!String.IsNullOrEmpty(values["genders"]))
                    {
                        patModel.Gender = values["genders"];
                    }
                    // Profile is valid, save it.
                    if (_Service.SaveProfile(Session["username"].ToString(), Session["password"].ToString(), patModel))
                        ViewData["SaveProfile"] = true;
                    else
                        ViewData["SaveProfile"] = false;
                }
                catch (Exception ex)
                {
                    logger.Error("Function Name: Save  Message: " + ex.Message + "");
                }
            }
            IntializeSelectLists(patModel);
            if (patModel.Title == "Select")
                patModel.Title = "";
            if (patModel.JuniorSenior == "Select")
                patModel.JuniorSenior = "";
            return View("Index", patModel);
        }

My IntializeSelectLists function:

public void IntializeSelectLists(PatientModel pm)
        {
            seniority = new[] { "Select", "Jr.", "Sr." };
            List<SelectListItem> JuniorSenior = new List<SelectListItem>();
            foreach (string item in seniority)
            {
                SelectListItem alb = new SelectListItem { Text = item, Value = item };
                JuniorSenior.Add(alb);
            }
            ViewData["seniority"] = JuniorSenior;
        }

Any help would be appreciated.

tereško
  • 58,060
  • 25
  • 98
  • 150
Farhan Ahmad
  • 5,148
  • 6
  • 40
  • 69
  • What is the value of `m.JuniorSenior` when the exception is thrown? – lukiffer May 23 '12 at 20:10
  • m.JuniorSenior can be ("", "Jr.", "Sr.") depending on what the user selects. But like I said, the error only occurs when the date of birth is before 150 years from today. If the date is between 150 years from today, everything works fine. – Farhan Ahmad May 23 '12 at 20:13
  • Could you please show your POST controller action that receives the form submission? – Darin Dimitrov May 23 '12 at 20:14
  • When the exception is thrown, what is the exact value of `m.JuniorSenior`? And what is the value of `ViewData["seniority"]` – lukiffer May 23 '12 at 20:17
  • Thanks. You don't seem to be populating `ViewData["seniority"]` before returning the view. See my answer. – Darin Dimitrov May 23 '12 at 20:26
  • Sorry I forgot to add that code. – Farhan Ahmad May 23 '12 at 20:26
  • I have found a couple of other posts [here](http://stackoverflow.com/questions/2334293/dynamic-range-validation-in-asp-net-mvc-2) and [here](http://stackoverflow.com/questions/2334293/dynamic-range-validation-in-asp-net-mvc-2) that point to the RangeAttribute having some issues. It sure looks like its stomping on something. – user957902 May 23 '12 at 21:28
  • You might want to ask yourself if there is any value in checking whether a date of birth is at most 150 years in the past, and why that is a better number than 149 years. – Kajetan Abt May 24 '12 at 13:52
  • I answered my own question. I found what the problem was. Thanks for your suggestion :) – Farhan Ahmad May 24 '12 at 13:57

1 Answers1

0

After bumping my head around I final found what the problem was.

In my IntializeSelectLists() I was populating the genders list right before the JuniorSenior list. As it turns out, the pm.Gender was returning null and therefore causing an exception.

The reason it was crashing at m.JuniorSenior was because I was displaying that before the m.Gender. So m.JuniorSenior was always null because the code didn't get to the point where it populated the m.JuniorSenior.

patModel.Gender = values["genders"].Trim();

I solved the problem by adding this in my Save().

Thanks to everyone that took the time to help me :)

Farhan Ahmad
  • 5,148
  • 6
  • 40
  • 69