0
votes

The Html.LabelFor works fine, so why not Html.ValidationMessageFor? My partial view looks like;

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<SHP.WebUI.Models.OtherLeaveViewModel>" %>
<% var unique = DateTime.Now.Ticks.ToString(); %>
<script language="javascript" type="text/javascript">
    $(document).ready(function () {
        $('#EmployeeOtherLeave_OtherLeaveDate').datepicker({ dateFormat: 'dd-MM-yy' });
        $('#MorningOnlyFlag').click(function () {
            $('#AfternoonOnlyFlag').attr('checked', false);
        })
        $('#AfternoonOnlyFlag').click(function () {
            $('#MorningOnlyFlag').attr('checked', false);
        })
    });

    var options = {
        target: '#frmAddAbsenceOneDay<%= unique %>',
        success: RefershList
    };

    $(document).ready(function () {
        $('#frmAddAbsenceOneDay<%= unique %>').ajaxForm(options);
    });

</script>

<div id="AddAbsenceOnDay<%= unique %>">
    <% using (Html.BeginForm("AddAbsenceOneDay", "Employee", FormMethod.Post,
           new { id = "frmAddAbsenceOneDay" + unique }))
       { %>
        <%: Html.ValidationSummary(true) %>
        <fieldset>
            <legend>Add an absence for a day or half day</legend>
            <table>
                <tr>
                    <td><%: Html.LabelFor(model => model.EmployeeOtherLeave.OtherLeaveId)%></td>
                    <td>
                <%: Html.DropDownListFor(model => model.EmployeeOtherLeave.OtherLeaveId, Model.LeaveList, "<--Select-->")%>
                <%: Html.ValidationMessageFor(model => model.EmployeeOtherLeave.OtherLeaveId)%>                    
                    </td>
                </tr>
                <tr>
                    <td>
                <%: Html.LabelFor(model => model.EmployeeOtherLeave.OtherLeaveDate)%>                    
                    </td>
                    <td>
                <%: Html.EditorFor(model => model.EmployeeOtherLeave.OtherLeaveDate)%>
                <%: Html.ValidationMessageFor(model => model.EmployeeOtherLeave.OtherLeaveDate)%>                    
                    </td>
                </tr>
                <tr>
                    <td>
                <%: Html.LabelFor(model => model.EmployeeOtherLeave.MorningOnlyFlag)%>
                    </td>
                    <td>
                <%: Html.CheckBoxFor(model => model.EmployeeOtherLeave.MorningOnlyFlag)%>
                <%: Html.ValidationMessageFor(model => model.EmployeeOtherLeave.MorningOnlyFlag)%>                        
                    </td>
                </tr>
                <tr>
                    <td>
                <%: Html.LabelFor(model => model.EmployeeOtherLeave.AfternoonOnlyFlag)%>
                    </td>
                    <td>
                <%: Html.CheckBoxFor(model => model.EmployeeOtherLeave.AfternoonOnlyFlag)%>
                <%: Html.ValidationMessageFor(model => model.EmployeeOtherLeave.AfternoonOnlyFlag)%>                     
                    </td>
                </tr>
            </table>

            <p>
                <span style="padding-right:10px;"><input type="submit" value="Create" /></span><input type="button" value="Close" onclick="closeTab()" />
            </p>
        </fieldset>
    <% } %>
    </div>

My buddy class looks like;

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using SHP.WebUI.Utility;
using System.ComponentModel.DataAnnotations;
using System.Web.Mvc;
using System.ComponentModel;

namespace SHP.Models
{
    [MetadataType(typeof(EmployeeOtherLeaf.Metadata))]
    public partial class EmployeeOtherLeaf
    {
        public string OtherLeaveName
        {
            get
            {
                if (this.OtherLeaf == null || this.OtherLeaf.OtherLeaveName == null)
                    return string.Empty;
                else
                    return this.OtherLeaf.OtherLeaveName;
            }
        }
        public EmployeeOtherLeaf() { }

        #region static methods

        #region methods

        #region "Buddy class" for validation
        /// <summary>
        /// This "buddy class" provides validation for a class generated from EF
        /// </summary>
        private sealed class Metadata
        {
            [HiddenInput(DisplayValue = false)]
            public int EmployeeOtherLeaveId { get; set; }
            [HiddenInput(DisplayValue = false)]
            public int EmployeeId { get; set; }

            [DisplayName("Leave Type")]
            [UIHint("DropDownList")]
            [Required(ErrorMessage = "Leave Type is required")]
            public int OtherLeaveId { get; set; }

            [DisplayName("Date")]
            [DataType(DataType.Date)]
            [Required(ErrorMessage = "Date is required")]
            public DateTime OtherLeaveDate
            {
                get { return Convert.ToDateTime(this.OtherLeaveDate); }
                set { this.OtherLeaveDate = Convert.ToDateTime(value); }
            }

            [DisplayName("Morning Only")]
            public bool MorningOnlyFlag
            {
                get { return Convert.ToBoolean(this.MorningOnlyFlag); }
                set { this.MorningOnlyFlag = Convert.ToBoolean(value); }
            }

            [DisplayName("Afternoon Only")]
            public bool AfternoonOnlyFlag
            {
                get { return Convert.ToBoolean(this.AfternoonOnlyFlag); }
                set { this.AfternoonOnlyFlag = Convert.ToBoolean(value); }
            }
        }
        #endregion  
    }
}

* ADDED INFO * I have since flattened the model and the new view looks like this;

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<SHP.Models.EmployeeOtherLeaf>" %>
<% var unique = DateTime.Now.Ticks.ToString(); %>
<script language="javascript" type="text/javascript">
    $(document).ready(function () {
        $('#EmployeeOtherLeave_OtherLeaveDate').datepicker({ dateFormat: 'dd-MM-yy' });
        $('#MorningOnlyFlag').click(function () {
            $('#AfternoonOnlyFlag').attr('checked', false);
        })
        $('#AfternoonOnlyFlag').click(function () {
            $('#MorningOnlyFlag').attr('checked', false);
        })
    });

    var options = {
        target: '#frmAddAbsenceOneDay<%= unique %>',
        success: RefershList
    };

    $(document).ready(function () {
        $('#frmAddAbsenceOneDay<%= unique %>').ajaxForm(options);
    });

</script>

<div id="AddAbsenceOnDay<%= unique %>">
    <%Html.EnableClientValidation(); %>
    <% using (Html.BeginForm("AddAbsenceOneDay", "Employee", FormMethod.Post,
           new { id = "frmAddAbsenceOneDay" + unique }))
       { %>
        <%: Html.ValidationSummary(true) %>
        <fieldset>
            <legend>Add an absence for a day or half day</legend>
            <table>
                <tr>
                    <td><%: Html.LabelFor(model => model.OtherLeaveId)%></td>
                    <td>
                <%: Html.DropDownListFor(model => model.OtherLeaveId, Model.SelectLeaveTypeList, "<--Select-->")%>
                <%: Html.ValidationMessageFor(model => model.OtherLeaveId)%>                    
                    </td>
                </tr>
                <tr>
                    <td>
                <%: Html.LabelFor(model => model.OtherLeaveDate)%>                    
                    </td>
                    <td>
                <%: Html.EditorFor(model => model.OtherLeaveDate)%>
                <%: Html.ValidationMessageFor(model => model.OtherLeaveDate)%>                    
                    </td>
                </tr>
                <tr>
                    <td>
                <%: Html.LabelFor(model => model.MorningOnlyFlag)%>
                    </td>
                    <td>
                <%: Html.CheckBoxFor(model => model.MorningOnlyFlag)%>
                <%: Html.ValidationMessageFor(model => model.MorningOnlyFlag)%>                        
                    </td>
                </tr>
                <tr>
                    <td>
                <%: Html.LabelFor(model => model.AfternoonOnlyFlag)%>
                    </td>
                    <td>
                <%: Html.CheckBoxFor(model => model.AfternoonOnlyFlag)%>
                <%: Html.ValidationMessageFor(model => model.AfternoonOnlyFlag)%>                     
                    </td>
                </tr>
            </table>

            <p>
                <span style="padding-right:10px;"><input type="submit" value="Create" /></span><input type="button" value="Close" onclick="closeTab()" />
            </p>
        </fieldset>

    <% } %>
    </div>
2
Are you using this as a control? How does this view get called?John Farrell

2 Answers

0
votes

I found the problem with the Javascript spelling mistake; RefershList should be RefreshList. I put that right and it works.

0
votes

The metadata buddy class works alongside your regular model. You should never actually access the members contained within the buddy class.

 <%: Html.CheckBoxFor(model => model.EmployeeOtherLeave.MorningOnlyFlag)%>
 <%: Html.ValidationMessageFor(model => model.EmployeeOtherLeave.MorningOnlyFlag)%>      

Should be:

 <%: Html.CheckBoxFor(model => model.MorningOnlyFlag)%>
 <%: Html.ValidationMessageFor(model => model.MorningOnlyFlag)%>       

Whats happening you validate your actual model the ModelState entries probably contain keys like "MorningOnlyFlag". When you use the ValidationMessageFor with the metadata class members you would be requesting ModelState entries with the key "EmployeeOtherLeave.MorningOnlyFlag".


You this is recursive right and will always throw a Stackoverflow exception?

public DateTime OtherLeaveDate
        {
            get { return Convert.ToDateTime(this.OtherLeaveDate); }
            set { this.OtherLeaveDate = Convert.ToDateTime(value); }
        }

Are you calling UpdateModel anywhere or using EmployeeOtherLeaf as the parameter as an action method? UpdateModel is what performs the model validation.