ASP.NET MVC2 应用程序的自定义验证规则

发布于 2024-10-03 21:49:55 字数 6490 浏览 3 评论 0原文

我正在尝试向我的应用程序添加验证。在允许将信息写入数据库之前,我需要检查一些规则。我已将基本数据验证添加到模型中,但我还需要确保如果一个字段具有特定值,则另一个字段是必需的。曾经,asp.net 上的 NerdDinner 教程涵盖了这一点,我过去使用它进行验证,但现在我找不到这个或任何其他例子。这是我的模型:

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

我的控制器:

    //
    // 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 未设置为 false,尽管 IsValid 中的代码已运行并且确实返回 RuleViolation。所以我手动检查 IsValid 它返回 false。当我返回视图时,错误消息不会出现。我可能会缺少什么?以下是一些观点的片段。

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>

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>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

瑶笙 2024-10-10 21:49:55

这非常简单 - 您只需将验证属性应用于整个模型(或子类)。然后,验证属性会获取对模型的引用,而不仅仅是一个属性,并且您可以对多个属性执行检查。

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.

萌吟 2024-10-10 21:49:55

您应该查看密码验证以获取如何执行此操作的示例。

在此处查看 PropertiesMustMatch 验证器:

http://msdn.microsoft.com/en-我们/杂志/ee336030.aspx

You should look at password validation for an example of how to do this.

Check out the PropertiesMustMatch validator here:

http://msdn.microsoft.com/en-us/magazine/ee336030.aspx

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文