MVC3自定义服务器端数据注释验证在部分视图中不起作用



我正试图通过数据注释添加自定义数据验证。在这一点上,我只关心服务器端验证。我在这里和其他地方看到的所有内容都引用了客户端验证。我已经剥离了所有的代码,运行了一些测试用例,我可以在常规视图中正常工作,但一旦表单处于部分视图中,代码就不再打断方法来覆盖IsValid。

在任何一种情况下,我都可以看到自定义属性正在初始化。当表单处于常规视图中时,我可以在提交表单时看到正在执行的覆盖方法,但当处于部分视图时,代码永远不会被执行,而是直接进入HttpPost操作。

我花了两天的大部分时间试图弄清楚这一点,但我不知所措。如有任何帮助,我们将不胜感激。

注:下面的代码在进入HttpPost操作时确实返回了相同的视图。我有这样的测试目的。我知道我的覆盖从来没有从局部视图调用过,因此IsValid总是真的。

显示验证工作的表单的视图

@model eRecruitBoard.ViewModels.HomeIndexViewModel
@{
ViewBag.Title = "eRecruitBoard";
}
@*<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>*@
<h2>Login/homepage</h2>
<br /><br />
<div class="errorMessage">
@Html.DisplayFor(m => m.LoginErrorMsg)
</div>
<br />
@using (Html.BeginForm("Index", "Home")) {
<div id="loginControlBox">
<fieldset>
<legend>Welcome to eRecruitBoard</legend> 
<div class="editor-label">
@Html.LabelFor(m => m.UserName)
</div>
<div class="editor-field">
@Html.TextBoxFor(m => m.UserName)
@Html.ValidationMessageFor(m => m.UserName)
</div>
<div class="editor-label">
@Html.LabelFor(m => m.Password)
</div>
<div class="editor-field">
@Html.PasswordFor(m => m.Password)
@Html.ValidationMessageFor(m => m.Password)
</div>
<div class="editor-label">
@Html.CheckBoxFor(m => m.RememberMe)
@Html.LabelFor(m => m.RememberMe)
</div>
<div class="editor-label">
@Html.EditorFor(m => m.Date)
@Html.ValidationMessageFor(m => m.Date)
</div>
<p>
<input type="submit" value="Log In" />
</p>
</fieldset>
</div>
}
<div>
@Html.Action("BlankForm", "TestForm")
</div>

部分视图(这些脚本调用也通过_Layout进入,但我在这里也进行了测试)

@model eRecruitBoard.ViewModels.TestFormViewModel
<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/MicrosoftAjax.js")" type="text/javascript"></script>    
<script src="@Url.Content("~/Scripts/MicrosoftMvcAjax.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/MicrosoftMvcValidation.js")" type="text/javascript"></script>
@using (Html.BeginForm("NewActivity2", "TestForm", FormMethod.Post))
{
<fieldset>
<legend>Test Form</legend>
<br />
@Html.LabelFor(m => m.Date)
@Html.EditorFor(m => m.Date)
@Html.ValidationMessageFor(m => m.Date)
<input id="activityTimelineSubmit" type="submit" value="Submit" />
</fieldset>
}

ViewModel(局部视图)

namespace eRecruitBoard.ViewModels
{
public class TestFormViewModel
{
[Required]
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:MM/dd/yyyy}")]
[NonFutureDate()]
[Display(Name = "Date")]
public DateTime Date { get; set; }
}
}

控制器(局部视图)

namespace eRecruitBoard.Controllers
{
public class TestFormController :BaseController
{
public ActionResult BlankForm()
{
var viewModel = new TestFormViewModel
{
Date = DateTime.Today
};
return PartialView("_TestForm", viewModel);
}
[HttpPost]
public ActionResult NewActivity2(DateTime Date)
{
if (!ModelState.IsValid)
return RedirectToAction("Index", "Home");
else
return RedirectToAction("Index", "Home");
}
}
}

验证码

using System;
using System.ComponentModel.DataAnnotations;
namespace eRecruitBoard.WebLibrary.Validation
{
[AttributeUsageAttribute(AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)]
public class NonFutureDateAttribute : ValidationAttribute  //public sealed class 
{
public NonFutureDateAttribute(): base("Activity can only be saved for today or dates in the past.")
{
}
public override bool IsValid(object value)
{
DateTime dateToCheck = (DateTime)value;
return (dateToCheck <= DateTime.Today);
}
}
}

如果RedirectToAction,则会丢失所有验证。您必须在POST操作中return PartialView(model)。这将需要将参数类型NewActivity2更改为TestFormViewModel而不是DateTime

如果部分视图(@Html.Partial()或javascript)仍然不起作用,请使用显示部分视图的示例更新代码。

最新更新