简体   繁体   English

ASP.NET 5:嵌套模型属性无法验证

[英]ASP.NET 5: Nested model properties not validating

I have added the following filter to return bad requests upon model validation errors: 我添加了以下过滤器,以在模型验证错误时返回不良请求:

public class ValidateModelFilterAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext context)
    {
        if (!context.ModelState.IsValid)
        {
            context.Result = new BadRequestObjectResult(context.ModelState);
        }

        base.OnActionExecuting(context);
    }
}

I have a two-layered model, ie: 我有一个两层模型,即:

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; }
}

The problem here is that only the properties of PersonModel are being validated. 这里的问题是仅验证PersonModel的属性。

Why would AddressModel properties not be validated? 为什么AddressModel属性进行验证?

Note: This is for WebApi! 注意:这是针对WebApi的!

I've managed to recreate your issue but in my case, it worked just fine. 我已经设法重新创建了您的问题,但就我而言,它工作得很好。

The only difference is that I haven't created the custom FilterAttribute like you did. 唯一的区别是,我没有像您那样创建自定义FilterAttribute

In short, I've created a new MVC 6 application using VS 2015. I've chosen the Web Application in the ASP.NET 5 Preview Template and kept the Individual User Accounts as the Authentication. 简而言之,我使用VS 2015创建了一个新的MVC 6应用程序。我已经在ASP.NET 5预览模板中选择了Web应用程序 ,并保留了“ 个人用户帐户”作为身份验证。

By doing so, this allowed me to have an up-and-running sample without having to add all the jquery files and whatnot. 这样,这使我可以运行并运行示例,而不必添加所有jquery文件等。

I then looked at how the Register.cshtml view was done for inspiration. 然后,我查看了Register.cshtml视图是如何获得灵感的。

I've managed to successfully create two models PersonModel and AddressModel and added the same properties you did. 我成功地创建了两个模型PersonModelAddressModel并添加了与您相同的属性。

I then created a new Controller and two IActionResult . 然后,我创建了一个新的Controller和两个IActionResult One for rendering the view (strongly typed) and another for when posting the <form> . 一种用于呈现视图(强类型),另一种用于发布<form>

The end result is that the client validation works perfectly fine with nested ViewModels as long as your fields inside your view respects the naming convention and...of course, as long as you have the appropriate validate.js and validate.unobtrusive.js files in there. 最终结果是,只要您的视图中的字段遵守命名约定,客户端验证就可以与嵌套ViewModels完美配合,当然,只要您具有适当的validate.jsvalidate.unobtrusive.js文件,在那里。

No need for that custom FilterAttribute . 无需该自定义FilterAttribute

Here is my View: 这是我的观点:

<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"); }
}

Notice the Address.Street naming convention for the fields which respects the nested ViewModels . 请注意尊重嵌套ViewModels的字段的Address.Street命名约定。

Also notice the @section Scripts which renders a partial and the partial has the following: 还请注意@section Scripts ,该@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>

It doesn't work, because the implementation is not checking nested properties if a parent model is null. 它不起作用,因为如果父模型为null,则实现不检查嵌套属性。 This makes sense, because there is nothing to validate! 这是有道理的,因为没有要验证的东西!

Below will result in a validation error stating that the address property is missing 下面将导致验证错误,指出address属性丢失

{
    "name" : "name",
}

Response for above: 以上回应:

{
  "Address": [
    "Field Address is required."
  ]
}

Seems correct isn't it? 似乎正确,不是吗?

To get the address validated you need to provide it as an empty object or full object with corresponding properties nulled or empty: 要验证地址,您需要将其提供为空对象或完整对象,并具有相应的属性为null或空:

{
     "name" : "name",
     "address" : {
     }
}

Response: 响应:

{
  "Address.Street": [
    "Field Street is required."
  ],
  "Address.City": [
    "Field City is required."
  ]
}

If you don't want to force your client to send the object if it doesn't have any values for it, create flattened viewmodel. 如果不想强迫客户端发送没有任何值的对象,请创建展平的viewmodel。

Hope this helps 希望这可以帮助

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM