MVC3服务器验证未触发

时间:2011-08-04 15:37:42

标签: asp.net asp.net-mvc-3 validation razor

我有一个带有StartDate和EndDate的ViewModel。显然,我需要验证StartDate< = EndDate。

我创建了StartDateBeforeEndDate验证属性并用它装饰了ViewModel类:

public class ValidProgramDisplayStartDateAttribute : ValidationAttribute
{
    public override bool IsValid(object value)
    {
        ProgramCreateOrEditViewModel vm = value as ProgramCreateOrEditViewModel;
        if (vm == null) return true; //not our problem

        if (!vm.EndDisplay.HasValue) return true; 
            //if you don't set an end date, you can't be invalid

        return vm.StartDisplay <= vm.EndDisplay;
    }
}

...

[ValidProgramDisplayStartDate(ErrorMessage="The program start display date cannot be after the program display end date.")]
public class ProgramCreateOrEditViewModel
{

    [Required(ErrorMessage = "A program title is required.")]
    [StringLength(255, ErrorMessage = "The program title cannot exceed 255 characters.")]
    public virtual string Title { get; set; }

    private DateTime _startDisplayDate = DateTime.Now;

    [Display(Name = "Display Start Date")]
    [Required(ErrorMessage = "A start display date is required")]
    [DataType(DataType.Date)]
    public virtual DateTime StartDisplay { get { return _startDisplayDate; } set { _startDisplayDate = value; } }

    [Display(Name="Display End Date")]
    [DataType(DataType.Date)]
    public virtual DateTime? EndDisplay { get; set; }

...more properties omitted...
}

标题已正确验证,其验证消息按预期显示在验证摘要中,但IsValid上的断点永远不会触发,如果您提供无效配对,则不会出现验证错误。

ValidationAttribute在创建ViewModel对象的单元测试中正常工作,填充日期,创建ValidationAttribute对象并调用其IsValid方法。如果我在Controller中的POST操作上设置断点,它也可以正常工作,并使用Visual Studio的即时窗口构造ValidationAttribute并将接收到的ViewModel传递给它。

我现在并不关心客户端验证;那是在“很高兴但有谁有时间”下提交的?但是,服务器端验证是必不可少的。

查看:

@model MyProject.Web.Mvc.Controllers.ViewModels.ProgramCreateOrEditViewModel
@using MvcContrib.FluentHtml
@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>
@using (Html.BeginForm())
{

<fieldset class="program"><legend>Program</legend>
    @if (!ViewData.ModelState.IsValid)
    {
        <p class="error">Please correct all errors listed below. The program cannot be saved while errors remain.</p>
        @Html.ValidationSummary(false)
    }
    @Html.HiddenFor(m => m.Id)
    <h3>
        @Html.LabelFor(m => m.Title)
        @Html.TextBoxFor(m => m.Title)</h3>
    <div id="accordion">
        <h3><a href="#">Dates:</a></h3>
        <div class="section">
            Dates related to <em>displaying</em> the program on our site:<br />
            @Html.LabelFor(m => m.StartDisplay)
            @Html.EditorFor(m => m.StartDisplay, new { _class = "date" })
            @Html.LabelFor(m => m.EndDisplay)
            @Html.EditorFor(m => m.EndDisplay, new { _class = "date enddisplay" })
        </div>
     ... more form fields omitted ...
    </div>
   <p>
        <input type="submit" value="Save" /></p>
</fieldset>
}

最后,编辑模板:

@model DateTime?
@Html.TextBox("", Model.HasValue ? Model.Value.ToString("MM/dd/yyyy") : String.Empty, new { @class = "date" })

2 个答案:

答案 0 :(得分:1)

很奇怪,以下代码对我很有帮助。

控制器:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        return View(new ProgramCreateOrEditViewModel
        {
            StartDisplay = DateTime.Now,
            EndDisplay = DateTime.Now.AddDays(-1),
            Title = "foo bar"
        });
    }

    [HttpPost]
    public ActionResult Index(ProgramCreateOrEditViewModel model)
    {
        return View(model);
    }
}

查看:

@model ProgramCreateOrEditViewModel

@using (Html.BeginForm())
{
    <fieldset class="program">
        <legend>Program</legend>

        @if (!ViewData.ModelState.IsValid)
        {
            <p class="error">Please correct all errors listed below. The program cannot be saved while errors remain.</p>
            @Html.ValidationSummary(false)
        }

        <h3>
            @Html.LabelFor(m => m.Title)
            @Html.TextBoxFor(m => m.Title)
        </h3>
        <div id="accordion">
            <h3><a href="#">Dates:</a></h3>
            <div class="section">
                Dates related to <em>displaying</em> the program on our site:<br />
                @Html.LabelFor(m => m.StartDisplay)
                @Html.EditorFor(m => m.StartDisplay, new { _class = "date" })
                @Html.LabelFor(m => m.EndDisplay)
                @Html.EditorFor(m => m.EndDisplay, new { _class = "date enddisplay" })
            </div>
        </div>
        <p><input type="submit" value="Save" /></p>
    </fieldset>
}

答案 1 :(得分:1)

问题似乎是,如果类属性中存在任何模型错误,则不会处理类ValidationAttribute。只有在类中的ValidationAttributes都满足后才会处理它。

出于您的目的,如果您将[ValidProgramDisplayStartDate(ErrorMessage="The program start display date cannot be after the program display end date.")]从装饰类移动到装饰您的Id属性,那么即使存在其他模型错误,您也将获得服务器端验证。

counsellorben