ASP.NET Core 3.x 三种【输入验证】方式 一、Data Annotation 二、自定义Atrribute 三、实现IValidatableObject接口

验证要做三件事

  1. 定义验证规则
  2. 按验证规则进行检查
  3. 报告验证的错误。
    在把错误报告给API消费者的时候,报告里并不包含到底是服务端还是API消费者引起的错误,这是状态码的工作。而通常响应的Body里面会包含一组验证错误信息,API消费者可以把这些信息展示给API消费者的用户。

定义验证规则

想要定义验证规则,我们可以使用ASP.NET Core内置的方式或者使用第三方库。
在ASP.NET Core里面,验证规则可以通过以下的方式来进行定义:

  • Data Annotations
  • 自定义Atrribute
  • 实现IValidatableObject接口

ASP.NET Core 内置了一个 ModelState对象,它用来做验证规则检查,如果规则验证不通过的话,ModelState.IsValid()方法就会返回false

public class TripManager    
{    
	[Key]    
	public int Id { get; set; }   
	[ForeignKey( "HotelID" )]    
	public Hotel Hotel { get; set; }   
	public int HotelID { get; set; }   
	[ForeignKey( "CarID" )]    
	public Car Car { get; set; }   
	public int CarID { get; set; }   
	[DataType( DataType.Date )]    
	public DateTime CheckInDate { get; set; }   
	[DataType( DataType.Date )]    
	public DateTime CheckOutDate { get; set; }   
	[Column( "TodaysPrice" )]    
	[Range( 10.30, 46.60 )]    
	public double Price { get; set; }   
	public Person Responsable { get; set; }    
}    
   
public class Hotel    
{    
    public int Id { get; set; }
    [DisplayFormat( NullDisplayText = "无名称" )]    
    public string Name { get; set; }    
} 

public class Person    
{    
    public int Id { get; set; }
    [Display(Name = "姓名")]
    [StringLength( 50,MininumLength = 10, ErrorMessage = "{0}的长度为{1}-{2}" )]    
    public string Name { get; set; }
    [NotMapped]    
    public List<Place> VisitedPlaces { get; set; }    
}

public class Car    
{    
    public int Id { get; set; }        
    [Required(ErrorMessage = "{0}字段为必填")]
	[MaxLength(100, ErrorMessage = "{0}的最大长度不能超过{1}"]
    public string Model { get; set; }    
    public string Brand { get; set; }    
}  

ASP.NET Core 2.x 以前的验证写法

if(!ModelState.IsValid)
{
	return UnprocessableEntity(ModeState);
}

ASP.NET Core 3.0 使用[ApiController]注解时就可以省略 2.x 这样的判断,有错则自动返回400错误

二、自定义Atrribute

public class TestAttribute:ValidationAttribute
{
	protected override ValidationResult IsValid(object value,ValidationContext validationContext)
	{
		var dto=(Hotel)validationContext.objectInstance;	//获取对象
		if(Name == "傻蛋")
		{
			return new ValidationResult("不能叫这么Low的名字",new[]{ nameof(Hotel)});			
		}
		return ValidationResult.Success;
	}
}

[Test]
public class Hotel
{    
    public int Id { get; set; }
    public string Name { get; set; } 
} 

说明

  1. [Test]作用于属性时, value指要验证的属性, validationContext指的是对象
  2. [Test]作用于时, valuevalidationContext相同,都指的是对象

三、实现IValidatableObject接口

public class Hotel:IValidatableObject
{    
    public int Id { get; set; }
    [Required]    
    public string Name { get; set; }    
	
	public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
	{
		if(Name == "傻蛋")
		{
			yield return new ValidationResult("不能叫这么Low的名字",new[]{ nameof(Name)});
		}
	}
} 

说明
先进行[ ]属性标签的验证,再时行Validate方法验证,Validate方法是“类”级别的。