[英]I need to return customized validation result (response) in validation attributes in ASP.Net core Web API
[英]How do I implement data validation attributes on a list of derived types in Asp Net Core 3.1 Web API
假設我有一個基礎 class 'animal' 和一個派生的 class 'dog' ,它具有一個新屬性(numberOfPaws)。
如果我創建一個接受“動物”列表的 controller,那么我希望我在“狗”class 上標記的數據驗證屬性將以通常的方式進行驗證。 如果超出范圍,我希望它們會被拒絕。 但是,盡管這適用於單個“動物”,但它不適用於“動物”列表/數組。
有沒有辦法讓這個列表工作,或者我必須在 controller 中編寫一些定制代碼?
感謝您的任何見解,請參閱下面的代碼。
public enum AnimalType
{
Dog = 0,
Cat = 1,
}
public class Animal
{
[Required]
public string Name {get ; set;}
public AnimalType Type {get ;set;}
}
public class Dog : Animal
{
[Required]
[Range(0, 4)] // hopefully 4 <3
public int NumberOfPaws{get ; set;}
}
[HttpPost("/animal/setAnimal")]
[AllowAnonymous]
public IActionResult SetAnimal([FromBody] Animal animal)
{
_logger.LogInformation("Send a dog with 5 paws here and observe it is rejected correctly");
return Ok();
}
[HttpPost("/animal/setAnimalList")]
[AllowAnonymous]
public IActionResult SetAnimalList([FromBody] List<Animal> animalList)
{
_logger.LogInformation("Send a list of dogs here and observe that although they are correctly deseriliazed they are allowed through with 5 paws :(");
return Ok();
}
請注意,我正在使用 JsonSubTypes ( https://github.com/manuc66/JsonSubTypes ) 以便通過“動物”基礎 class 中的 AnimalType 屬性正確序列化和反序列化派生類型。
如果有人有興趣觀察這一點,我很高興在 GitHub 上放置一個最小可重復示例。
我最終找到了解決方案,這不是我所說的“干凈”,但它似乎確實有效,所以我希望它可以幫助其他最終來到這里的人,如果你找到更好的解決方案,請告訴我。
如果您創建自定義數據屬性並覆蓋 IsValid() 方法,那么您可以在標識派生類型的類型上使用 switch 語句來驗證繼承的類型屬性。
將此屬性放在您的基礎 class(動物)上,驗證將返回標准 ASP.net 核心驗證問題詳細信息 object。
注意** 您可能不想對每個繼承的屬性進行驗證,而只是驗證整個繼承的 object。 我試過了,但陷入了無限的驗證循環。
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace Animal.Circus
{
[AttributeUsage(AttributeTargets.Class)]
public class AnimalAttribute : ValidationAttribute
{
// Not sure this is the perfect implementation of inhertited type validation but it works for now
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var animal = value as Animal;
var success = true;
var validationResults = new List<ValidationResult>();
switch (animal.Type)
{
case AnimalType.Dog:
{
var dog = (Dog)animal;
var ctx = new ValidationContext(dog);
ctx.MemberName = nameof(dog.NumberOfPaws);
success = success & Validator.TryValidateProperty(dog.NumberOfPaws, ctx, validationResults);
}
break;
case AnimalType.Animal:
// already validated by default
break;
default:
break;
}
if (!success)
{
return new ValidationResult(validationResults[0].ErrorMessage, validationResults[0].MemberNames);
}
else
{
return ValidationResult.Success;
}
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.