我正在编写一个ASP.NET Core Web应用程序。我正在使用MVC的模型验证框架,并且有一个“表单”模型,其中包含一个Product
对象和一个IsCreationMode
布尔值。
我想验证Product
,但是我也想确保,如果要创建产品,则该SKU尚不存在任何产品。因此,我定义了一个自定义验证属性,如果IsCreationMode
为true并且可以在数据库中找到产品SKU,则返回一个验证错误。我在模型类本身上使用了此属性,并且可以正常工作。
[ProductIsUnique]
public class ProductForm
{
public Product Product { get; set; }
public bool IsCreationMode { get; set; }
}
但是,如果产品对象无效,则然后将不验证模型对象(这意味着它始终被视为“有效”)。 (我尚未测试是否确实没有对任何对象(并非其所有成员都有效)进行验证。)
这意味着用户可能会看到有关产品某个属性的错误(例如,“名称过长”),然后进行修正,提交并得到另一个错误,因为整个模型都未经首次验证,但如果经过检查,将被视为无效。
是否有此配置设置?在我看来,“无论如何验证”都不是不受欢迎或不推荐的选择...
编辑
这是一个最小的例子。
创建一个新的ASP.NET Core MVC项目:
dotnet new mvc
将其放在HomeController.cs文件中:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Stack.Models;
using System.ComponentModel.DataAnnotations;
namespace Stack.Controllers
{
public class HomeController : Controller
{
[HttpGet]
public IActionResult Index()
{
ProductForm model = new ProductForm()
{
IsCreationMode = true
};
return View(model);
}
[HttpPost]
public IActionResult Index(ProductForm model)
{
if (!ModelState.IsValid)
return BadRequest(ModelState);
return Ok();
}
}
public class Product
{
public int ID { get; set; }
[StringLength(50, MinimumLength = 3)]
public string Name { get; set; }
}
[ProductIsUnique]
public class ProductForm
{
public Product Product { get; set; }
public bool IsCreationMode { get; set; }
}
public class ProductIsUniqueAttribute : ValidationAttribute
{
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
ProductForm productForm = validationContext.ObjectInstance as ProductForm;
if (productForm.IsCreationMode && productForm.Product.ID == 10)
{
return new ValidationResult(string.Format("A Product with ID '{0}' already exists. You cannot create another one.", productForm.Product.ID), new string[]
{
"Product.ID"
});
}
return ValidationResult.Success;
}
}
}
将此内容放入Views / Home / Index.cshtml:
@model Stack.Controllers.ProductForm
<form method="post">
<p>ID: @Html.TextBoxFor(m => m.Product.ID)</p>
<p>Name: @Html.TextBoxFor(m => m.Product.Name)</p>
@Html.HiddenFor(m => m.IsCreationMode)
<input type="submit" value="Submit" />
</form>
构建并运行。现在,如果您访问/
,您将收到一个包含两个字段的表单。
1)在ID中键入“ 10”以外的任何内容,在“名称”中键入3到50个字符之间的字符串。服务器按预期响应200 OK。
2)在ID中键入“ 10”,在“名称”中键入3到50个字符之间的字符串。服务器按预期响应400 BadRequest,并使用JSON描述一个错误,即ProductIsUnique
的错误。
3)键入“ 10”和少于3个字符的字符串。我预计会出现两个错误:无效的名称和ProductIsUnique
的失败。相反,我只会得到无效的名称。