Объект модели не проверяется, если член недействителен - PullRequest
0 голосов
/ 12 апреля 2019

Я пишу веб-приложение ASP.NET Core.Я использую инфраструктуру проверки модели 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) Введите в идентификаторе что-либо, кроме «10», а в имени - строку длиной от 3 до 50 символов.Сервер отвечает 200 OK, как и ожидалось.

2) Введите «10» в идентификаторе и строку длиной от 3 до 50 символов в имени.Сервер отвечает 400 BadRequest с JSON, описывающим одну единственную ошибку, т. Е. Ошибку из ProductIsUnique, как и ожидалось.

3) Введите «10» и строку короче 3 символов.Я ожидаю две ошибки: неверное имя и сбой от ProductIsUnique.Вместо этого я получаю только неверное имя.

...