ASP.NET 5:嵌套模型属性未验证
ASP.NET 5: Nested model properties not validating
我已将以下过滤器添加到 return 模型验证错误时的错误请求:
public class ValidateModelFilterAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext context)
{
if (!context.ModelState.IsValid)
{
context.Result = new BadRequestObjectResult(context.ModelState);
}
base.OnActionExecuting(context);
}
}
我有一个两层模型,即:
public class PersonModel
{
[Required] // This works!
public string Name { get; set; }
[Required] // This works!
public AddressModel Address { get; set; }
}
public class AddressModel
{
[Required] // This DOESN'T work :(
public string Street { get; set; }
[Required] // This DOESN'T work :(
public string City { get; set; }
}
这里的问题是只验证 PersonModel
的属性。
为什么 AddressModel
属性不会被验证?
注意:这是针对 WebApi 的!
我已经设法重现了您的问题,但就我而言,它工作得很好。
唯一的区别是我没有像你那样创建自定义 FilterAttribute
。
简而言之,我使用 VS 2015 创建了一个新的 MVC 6 应用程序。我在 ASP.NET 5 预览模板中选择了 Web 应用程序 并保留个人用户帐户 作为身份验证。
通过这样做,我可以得到一个升级 运行 样本,而不必添加所有 jquery
文件等等。
然后我查看了 Register.cshtml
视图是如何完成的以获得灵感。
我已经成功创建了两个模型 PersonModel
和 AddressModel
并添加了与您所做的相同的属性。
然后我创建了一个新的 Controller
和两个 IActionResult
。一个用于呈现视图(强类型),另一个用于发布 <form>
.
最终结果是客户端验证与嵌套 ViewModels
完美配合,只要您视图中的字段遵守命名约定,并且...当然,只要您有适当的 validate.js
和 validate.unobtrusive.js
文件。
不需要那个自定义 FilterAttribute
。
这是我的观点:
<form asp-controller="NewController" asp-action="Index" method="post" class="form-horizontal" role="form">
<h4>Create a new account.</h4>
<hr />
<div asp-validation-summary="ValidationSummary.All" class="text-danger"></div>
<div class="form-group">
<label asp-for="Name" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="Name" class="form-control" />
<span asp-validation-for="Name" class="text-danger"></span>
</div>
</div>
<div class="form-group">
<label asp-for="Address.Street" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="Address.Street" class="form-control" />
<span asp-validation-for="Address.Street" class="text-danger"></span>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<button type="submit" class="btn btn-default">Register</button>
</div>
</div>
</form>
@section Scripts {
@{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); }
}
请注意字段的 Address.Street
命名约定,它尊重嵌套的 ViewModels
。
另请注意 @section Scripts
,它呈现一个局部,局部具有以下内容:
<environment names="Development">
<script src="~/lib/jquery-validation/jquery.validate.js"></script>
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js"></script>
</environment>
它不起作用,因为如果父模型为空,实现不会检查嵌套属性。这是有道理的,因为没有什么可验证的!
以下将导致验证错误,指出地址 属性 缺失
{
"name" : "name",
}
以上回复:
{
"Address": [
"Field Address is required."
]
}
似乎是正确的,不是吗?
要验证地址,您需要将其作为空对象或具有相应属性为空或空的完整对象提供:
{
"name" : "name",
"address" : {
}
}
回复:
{
"Address.Street": [
"Field Street is required."
],
"Address.City": [
"Field City is required."
]
}
如果您不想强制客户端发送没有任何值的对象,请创建扁平化视图模型。
希望对您有所帮助
我已将以下过滤器添加到 return 模型验证错误时的错误请求:
public class ValidateModelFilterAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext context)
{
if (!context.ModelState.IsValid)
{
context.Result = new BadRequestObjectResult(context.ModelState);
}
base.OnActionExecuting(context);
}
}
我有一个两层模型,即:
public class PersonModel
{
[Required] // This works!
public string Name { get; set; }
[Required] // This works!
public AddressModel Address { get; set; }
}
public class AddressModel
{
[Required] // This DOESN'T work :(
public string Street { get; set; }
[Required] // This DOESN'T work :(
public string City { get; set; }
}
这里的问题是只验证 PersonModel
的属性。
为什么 AddressModel
属性不会被验证?
注意:这是针对 WebApi 的!
我已经设法重现了您的问题,但就我而言,它工作得很好。
唯一的区别是我没有像你那样创建自定义 FilterAttribute
。
简而言之,我使用 VS 2015 创建了一个新的 MVC 6 应用程序。我在 ASP.NET 5 预览模板中选择了 Web 应用程序 并保留个人用户帐户 作为身份验证。
通过这样做,我可以得到一个升级 运行 样本,而不必添加所有 jquery
文件等等。
然后我查看了 Register.cshtml
视图是如何完成的以获得灵感。
我已经成功创建了两个模型 PersonModel
和 AddressModel
并添加了与您所做的相同的属性。
然后我创建了一个新的 Controller
和两个 IActionResult
。一个用于呈现视图(强类型),另一个用于发布 <form>
.
最终结果是客户端验证与嵌套 ViewModels
完美配合,只要您视图中的字段遵守命名约定,并且...当然,只要您有适当的 validate.js
和 validate.unobtrusive.js
文件。
不需要那个自定义 FilterAttribute
。
这是我的观点:
<form asp-controller="NewController" asp-action="Index" method="post" class="form-horizontal" role="form">
<h4>Create a new account.</h4>
<hr />
<div asp-validation-summary="ValidationSummary.All" class="text-danger"></div>
<div class="form-group">
<label asp-for="Name" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="Name" class="form-control" />
<span asp-validation-for="Name" class="text-danger"></span>
</div>
</div>
<div class="form-group">
<label asp-for="Address.Street" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="Address.Street" class="form-control" />
<span asp-validation-for="Address.Street" class="text-danger"></span>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<button type="submit" class="btn btn-default">Register</button>
</div>
</div>
</form>
@section Scripts {
@{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); }
}
请注意字段的 Address.Street
命名约定,它尊重嵌套的 ViewModels
。
另请注意 @section Scripts
,它呈现一个局部,局部具有以下内容:
<environment names="Development">
<script src="~/lib/jquery-validation/jquery.validate.js"></script>
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js"></script>
</environment>
它不起作用,因为如果父模型为空,实现不会检查嵌套属性。这是有道理的,因为没有什么可验证的!
以下将导致验证错误,指出地址 属性 缺失
{
"name" : "name",
}
以上回复:
{
"Address": [
"Field Address is required."
]
}
似乎是正确的,不是吗?
要验证地址,您需要将其作为空对象或具有相应属性为空或空的完整对象提供:
{
"name" : "name",
"address" : {
}
}
回复:
{
"Address.Street": [
"Field Street is required."
],
"Address.City": [
"Field City is required."
]
}
如果您不想强制客户端发送没有任何值的对象,请创建扁平化视图模型。
希望对您有所帮助