记录一次RestFul风格的api-12(数据验证)
具体实现:(数据的输入)
1.添加数据验证。使用System.ComponentModel.DataAnnotations;
public class TouristRouteCreateDto { [Required(ErrorMessage="title 不可为空")] [MaxLength(100)] public string Title { get; set; } [Required] [MaxLength(1500)]
}
2.自定义数据验证。
具体的dto如下:
public class TouristRouteCreateDto : IValidatableObject { [Required(ErrorMessage="title 不可为空")] [MaxLength(100)] public string Title { get; set; } [Required] [MaxLength(1500)] public string Description { get; set; } // 计算方式=原价*折扣 public decimal? Price { get; set; } //public decimal originalPrice { get; set; } //public double? DiscountPresent { get; set; } public DateTime CreateTime { get; set; } public DateTime? updateTime { get; set; } public DateTime? DepartureTime { get; set; } public string Features { get; set; } public string Fees { get; set; } public string Notes { get; set; } public ICollection<TouristRoutePictureForCreationDto> TouristRoutePictures { get; set; } = new List<TouristRoutePictureForCreationDto>(); public double? Rating { get; set; }//评分 public string TravelDays { get; set; } public string TripType { get; set; } public string DepartureCity { get; set; } public IEnumerable<ValidationResult> Validate( ValidationContext validationContext) { if (Title == Description) { yield return new ValidationResult( "路线名称必须与路线描述不同", new[] { "TouristRouteCreateDto" } ); } } }
3.ValidationContext的自定义校验ValidationAttribute
public class TouristRouteTitleMustBeDifferentFromDescriptionAttribute : ValidationAttribute { protected override ValidationResult IsValid( object value, ValidationContext validationContext ) { var touristRouteDto = (TouristRouteForCreationDto)validationContext.ObjectInstance; if (touristRouteDto.Title == touristRouteDto.Description) { return new ValidationResult( "路线名称必须与路线描述不同", new[] { "TouristRouteCreateDto" } ); } return ValidationResult.Success; } }
[TouristRouteTitleMustBeDifferentFromDescriptionAttribute] public class TouristRouteForCreationDto //: IValidatableObject { [Required(ErrorMessage="title 不可为空")] [MaxLength(100)] public string Title { get; set; } [Required] [MaxLength(1500)] public string Description { get; set; } // 计算方式=原价*折扣 public decimal? Price { get; set; } //public decimal originalPrice { get; set; } //public double? DiscountPresent { get; set; } public DateTime CreateTime { get; set; } public DateTime? updateTime { get; set; } public DateTime? DepartureTime { get; set; } public string Features { get; set; } public string Fees { get; set; } public string Notes { get; set; } public ICollection<TouristRoutePictureForCreationDto> TouristRoutePictures { get; set; } = new List<TouristRoutePictureForCreationDto>(); public double? Rating { get; set; }//评分 public string TravelDays { get; set; } public string TripType { get; set; } public string DepartureCity { get; set; } //public IEnumerable<ValidationResult> Validate( // ValidationContext validationContext) //{ // if (Title == Description) // { // yield return new ValidationResult( // "路线名称必须与路线描述不同", // new[] { "TouristRouteCreateDto" } // ); // } //} }
4,修改返回状态码422.(400->422)startup.cs中。
public void ConfigureServices(IServiceCollection services) { services.AddControllers(setupAction => { setupAction.ReturnHttpNotAcceptable = true; }).AddXmlDataContractSerializerFormatters() .ConfigureApiBehaviorOptions(setupAction => { setupAction.InvalidModelStateResponseFactory = context => { var problemDetail = new ValidationProblemDetails(context.ModelState) { Type = "", Title = "数据验证失败", Status = StatusCodes.Status402PaymentRequired, Detail = "请看详细信息", Instance = context.HttpContext.Request.Path }; problemDetail.Extensions.Add("traceId", context.HttpContext.TraceIdentifier); return new UnprocessableEntityObjectResult(problemDetail) { ContentTypes = { "application/problem+json" } }; }; }) ; services.AddTransient<ITouristRouteRepository, TouristRouteRepository>(); services.AddDbContext<AppDbContext>(options => { options.UseSqlServer(Configuration.GetConnectionString("delfault")); }); // 加载automapper的pofile的文件 services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies()); }