【发布时间】:2011-12-30 12:22:58
【问题描述】:
我有一个 ViewModel,它有一些 DataAnnotations 验证,然后为了更复杂的验证实现 IValidatableObject 并使用 Validate 方法。
我所期待的行为是 this one:首先是所有的 DataAnnotations,然后,只有在没有错误的情况下,才使用 Validate 方法。我怎么发现这并不总是正确的。我的 ViewModel(演示版)有三个文件,一个 string,一个 decimal 和一个 decimal?。所有三个属性都只有Required 属性。对于string 和decimal?,行为是预期的行为,但对于decimal,当为空时,必需的验证失败(到目前为止还不错),然后执行Validate 方法。如果我检查该属性,它的值为零。
这里发生了什么?我错过了什么?
注意:我知道Required 属性是用来检查值是否为空的。所以我希望被告知不要在不可为空的类型中使用 Required 属性(因为它永远不会触发),或者,该属性以某种方式理解 POST 值并注意该字段未填充。在第一种情况下,该属性不应触发,而应触发 Validate 方法。在第二种情况下,属性应该触发并且 Validate 方法不应该触发。但我的结果是:属性触发和 Validate 方法触发。
这是代码(没什么特别的):
控制器:
public ActionResult Index()
{
return View(HomeModel.LoadHome());
}
[HttpPost]
public ActionResult Index(HomeViewModel viewModel)
{
try
{
if (ModelState.IsValid)
{
HomeModel.ProcessHome(viewModel);
return RedirectToAction("Index", "Result");
}
}
catch (ApplicationException ex)
{
ModelState.AddModelError(string.Empty, ex.Message);
}
catch (Exception ex)
{
ModelState.AddModelError(string.Empty, "Internal error.");
}
return View(viewModel);
}
型号:
public static HomeViewModel LoadHome()
{
HomeViewModel viewModel = new HomeViewModel();
viewModel.String = string.Empty;
return viewModel;
}
public static void ProcessHome(HomeViewModel viewModel)
{
// Not relevant code
}
视图模型:
public class HomeViewModel : IValidatableObject
{
[Required(ErrorMessage = "Required {0}")]
[Display(Name = "string")]
public string String { get; set; }
[Required(ErrorMessage = "Required {0}")]
[Display(Name = "decimal")]
public decimal Decimal { get; set; }
[Required(ErrorMessage = "Required {0}")]
[Display(Name = "decimal?")]
public decimal? DecimalNullable { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
yield return new ValidationResult("Error from Validate method");
}
}
查看:
@model MVCTest1.ViewModels.HomeViewModel
@{
Layout = "~/Views/Shared/_Layout.cshtml";
}
@using (Html.BeginForm(null, null, FormMethod.Post))
{
<div>
@Html.ValidationSummary()
</div>
<label id="lblNombre" for="Nombre">Nombre:</label>
@Html.TextBoxFor(m => m.Nombre)
<label id="lblDecimal" for="Decimal">Decimal:</label>
@Html.TextBoxFor(m => m.Decimal)
<label id="lblDecimalNullable" for="DecimalNullable">Decimal?:</label>
@Html.TextBoxFor(m => m.DecimalNullable)
<button type="submit" id="aceptar">Aceptar</button>
<button type="submit" id="superAceptar">SuperAceptar</button>
@Html.HiddenFor(m => m.Accion)
}
【问题讨论】:
-
decimal永远不会为空。它不能像string或decimal?那样为空。您期望的行为是什么? -
-
您必须将
decimal设置为可为空,否则 [必需] 将永远不会触发。有什么理由不这样做? -
意外行为是Required IS 触发。我收到了所需的消息(来自 DataAnnotations),并且 Validate 方法正在触发。我希望除非所有 DataAnnotations 都成功,否则不会触发 Validate 方法。
-
检查all this post,尤其是“Under-Posting”问题部分。我猜你正面临一个不那么预期的行为。
标签: asp.net asp.net-mvc asp.net-mvc-3 data-annotations ivalidatableobject