Q:

Custom validation rules for ASP.NET MVC2 Application

I am attempting to add validation to my application.  I have some rules I need to check before allowing the information to be written to the database.  I have the basic data validation added to the model, but I also need to make sure that if one field has a certain value, this other field is required.  At one time the NerdDinner tutorial at asp.net covered that and I used that in the past for validation, but now I can't find that or any other example.  Here is my model:
public class DayRequested
{
    public int RequestId { set; get; }
    [Required, DisplayName("Date of Leave")]
    public string DateOfLeave { get; set; }
    [Required, DisplayName("Time of Leave")]
    public string TimeOfLeave { get; set; }
    [Required, DisplayName("Hours Requested")]
    [Range(0.5, 24, ErrorMessage = "Requested Hours must be within 1 day")]
    public double HoursRequested { get; set; }
    [Required, DisplayName("Request Type")]
    public string RequestType { get; set; }
    [DisplayName("Specify Relationship")]
    public string Relationship { get; set; }
    [DisplayName("Nature of Illness")]
    public string NatureOfIllness { get; set; }
    public bool AddedToTimesheet { get; set; }

    public bool IsValid
    {
        get { return (GetRuleViolations().Count() == 0); }
    }

    public IEnumerable<RuleViolation> GetRuleViolations()
    {
        if (String. IsNullOrEmpty(DateOfLeave))
            yield return new RuleViolation("Date of Leave Required", "DateOfLeave");
        if (String. IsNullOrEmpty(TimeOfLeave))
            yield return new RuleViolation("Date of Leave Required", "TimeOfLeave");
        if ((HoursRequested < 0.5) || (HoursRequested > 24))
            yield return new RuleViolation("Hours must be in a period of one day", "HoursRequested");
        if (String. IsNullOrEmpty(RequestType))
            yield return new RuleViolation("Request Type is required", "RequestType");
        if ((! String. IsNullOrEmpty(NatureOfIllness)) && (NatureOfIllness. Length < 3))
            yield return new RuleViolation("Nature of Illness must be longer 2 characters", "NatureOfIllness");

        // Advanced data validation to make sure rules are followed
        LeaveRequestRepository lrr = new LeaveRequestRepository();
        List<LeaveRequestType> lrt = lrr. GetAllLeaveRequestTypes();
        LeaveRequestType workingType = lrt. Find(b => b.Id == Convert. ToInt32(RequestType));

        if ((String. IsNullOrEmpty(Relationship)) && (workingType. HasRelationship))
            yield return new RuleViolation("Relationship is Required", "Relationship");
        if ((String. IsNullOrEmpty(NatureOfIllness)) && (workingType. HasNatureOfIllness))
            yield return new RuleViolation("Nature of Illness is Required", "NatureOfIllness");

        yield break;
    }
}

My controller:
    //
    // POST: /LeaveRequest/Create
    [Authorize, HttpPost]
    public ActionResult Create(LeaveRequest leaveRequest, List<DayRequested> requestedDays)
    {
        if (ModelState. IsValid)
        {
            foreach (DayRequested requestedDay in requestedDays)
            {
                requestedDay. RequestId = leaveRequest. RequestId;
                requestedDay. NatureOfIllness = (String. IsNullOrEmpty(requestedDay. NatureOfIllness) ? "" :  requestedDay. NatureOfIllness);
                requestedDay. Relationship = (String. IsNullOrEmpty(requestedDay. Relationship) ? "" :  requestedDay. Relationship);

                if (requestedDay. IsValid)
                    lrRepository. CreateNewLeaveRequestDate(requestedDay);
                else
                    return View(new LeaveRequestViewModel(leaveRequest, requestedDays, lrRepository. GetLeaveRequestTypes()));
            }

            if (leaveRequest. IsValid)
                lrRepository. CreateNewLeaveRequest(leaveRequest);
            else
                return View(new LeaveRequestViewModel(leaveRequest, requestedDays, lrRepository. GetLeaveRequestTypes()));
        }
        else
            return View(new LeaveRequestViewModel(leaveRequest, requestedDays, lrRepository. GetLeaveRequestTypes()));

        return RedirectToAction("Index", lrRepository. GetLeaveRequests(udh.employeeId));
    }

ModelState. IsValid is not set to false though the code in IsValid is run and does return a RuleViolation.  So I manually check IsValid it returns false.  When I return to the view, the error messages do not appear.  What might I be missing?  Here are some snippets of the views. 
Create.aspx
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
    <h2>Create New Leave Request</h2>
    <div><%= Html. ActionLink("Back to List", "Index") %></div>
    <%= Html. Partial("RequestEditor", Model) %>
    <div><%= Html. ActionLink("Back to List", "Index") %></div>
</asp:Content>

RequestEditor.ascx
<% using (Html. BeginForm()) {%>
    <%= Html. ValidationSummary(true) %>
        <table id="editorRows">
            <% foreach (var item in Model. DaysRequested)
                Html. RenderPartial("RequestedDayRow", new EmployeePayroll. ViewModels. LeaveRequestRow(item, Model. LeaveRequestType)); %>
        </table>
        <p>Type your time to sign your request.</p>
        <p><%= Html. LabelFor(model => model. LeaveRequest. EmployeeSignature) %>: 
            <%= Html. TextBoxFor(model => model. LeaveRequest. EmployeeSignature, new { Class="required" })%>
            <%= Html. ValidationMessageFor(model => model. LeaveRequest. EmployeeSignature)%></p>
        <p><input type="submit" value="Submit Request" /></p>
<% } %>

RequestedDayRow.ascx
<tbody class="editorRow">
    <tr class="row1"></tr>
    <tr class="row2">
        <td colspan="2" class="relationship">
            <%= Html. LabelFor(model => model. DayRequested. Relationship)%>:
            <%= Html. TextBoxFor(model => model. DayRequested. Relationship) %>
            <%= Html. ValidationMessageFor(model => model. DayRequested. Relationship)%>
        </td>
        <td colspan="2" class="natureOfIllness">
            <%= Html. LabelFor(model => model. DayRequested. NatureOfIllness)%>:
            <%= Html. TextBoxFor(model => model. DayRequested. NatureOfIllness) %>
            <%= Html. ValidationMessageFor(model => model. DayRequested. NatureOfIllness)%>
        </td>
        <td></td>
    </tr>
</tbody>

A:

It's quite simple - you just need to apply your validation attribute to the entire model (or a child class).  Then the validation attribute gets a reference to the model instead of just one property and you can perform your checks on multiple properties. 