我们有 API Controller ,它通过 Request Dto 获取产品数据。为了使类成员成为必需的,我们需要在 Dto 中放置 Required
属性。否则服务可以使用空成员执行。
https://learn.microsoft.com/en-us/aspnet/core/mvc/models/validation?view=aspnetcore-3.1
目前 Request DTO 有 20 多个成员,在所有类成员中编写 [Required]
看起来非常重复。
我的问题是,为什么需要RequiredAttribute?我们已经有了 int 和可为 null 的成员。数据类型本身不应该强制执行契约吗?
有没有一种方法可以自动化并让类成员强制执行必需的,而无需到处编写?
[HttpPost]
[Route("[action]")]
public async Task<ActionResult<ProductResponse>> GetProductData(BaseRequest<ProductRequestDto> request)
{
var response = await _productService.GetProductItem(request);
return Ok(response);
public class ProductRequestDto
{
public int ProductId { get; set; }
public bool Available { get; set; }
public int BarCodeNumber{ get; set; }
....
How to add custom error message with “required” htmlattribute to mvc 5 razor view text input editor
public class ProductRequestDto
{
[Required]
public int ProductId { get; set; }
[Required]
public bool Available { get; set; }
[Required]
public int BarCodeNumber{ get; set; }
....
最佳答案
如果您愿意使用 Fluent Validation你可以这样做:
该验证器可以使用反射验证任何 dto
验证器:
using FluentValidation;
using System;
using System.Collections.Generic;
using System.Text;
namespace ConsoleTests
{
public class MyValidator : AbstractValidator<ModelDTO>
{
public MyValidator()
{
foreach (var item in typeof(ModelDTO).GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance))
{
Console.WriteLine($"Name: {item.Name}, Type: {item.PropertyType}");
if (item.PropertyType == typeof(int))
{
RuleFor(x => (int)item.GetValue(x, null)).NotEmpty<ModelDTO,int>();
}
else
{
RuleFor(x => (string)item.GetValue(x, null)).NotEmpty<ModelDTO, string>();
}
//Other stuff...
}
}
}
}
NotEmpty
拒绝 null 和默认值。
程序.cs
using System;
using System.ComponentModel.DataAnnotations;
using System.IO;
namespace ConsoleTests
{
class Program
{
static void Main(string[] args)
{
try
{
ModelDTO modelDTO = new ModelDTO
{
MyProperty1 = null, //string
MyProperty2 = 0, //int
MyProperty3 = null, //string
MyProperty4 = 0 //int
};
MyValidator validationRules = new MyValidator();
FluentValidation.Results.ValidationResult result = validationRules.Validate(modelDTO);
foreach (var error in result.Errors)
{
Console.WriteLine(error);
}
Console.WriteLine("Done!");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
}
输出:
Name: MyProperty1, Type: System.String
Name: MyProperty2, Type: System.Int32
Name: MyProperty3, Type: System.String
Name: MyProperty4, Type: System.Int32
must not be empty.
must not be empty.
must not be empty.
must not be empty.
Done!
为了获得更完整的解决方案: 看到这个问题how-to-use-reflection-in-fluentvalidation .
它使用相同的概念,验证器采用 PropertyInfo
并通过获取类型和值来进行验证。
以下代码来自上述问题。
属性验证器:
public class CustomNotEmpty<T> : PropertyValidator
{
private PropertyInfo _propertyInfo;
public CustomNotEmpty(PropertyInfo propertyInfo)
: base(string.Format("{0} is required", propertyInfo.Name))
{
_propertyInfo = propertyInfo;
}
protected override bool IsValid(PropertyValidatorContext context)
{
return !IsNullOrEmpty(_propertyInfo, (T)context.Instance);
}
private bool IsNullOrEmpty(PropertyInfo property, T obj)
{
var t = property.PropertyType;
var v = property.GetValue(obj);
// Omitted for clarity...
}
}
规则生成器:
public static class ValidatorExtensions
{
public static IRuleBuilderOptions<T, T> CustomNotEmpty<T>(
this IRuleBuilder<T, T> ruleBuilder, PropertyInfo propertyInfo)
{
return ruleBuilder.SetValidator(new CustomNotEmpty<T>(propertyInfo));
}
}
最后是验证器:
public class FooValidator : AbstractValidator<Foo>
{
public FooValidator(Foo obj)
{
// Iterate properties using reflection
var properties = ReflectionHelper.GetShallowPropertiesInfo(obj);//This is a custom helper that retrieves the type properties.
foreach (var prop in properties)
{
// Create rule for each property, based on some data coming from other service...
RuleFor(o => o)
.CustomNotEmpty(obj.GetType().GetProperty(prop.Name))
.When(o =>
{
return true; // do other stuff...
});
}
}
}
关于c# - Net Core : Enforce Required Class Members in Request API Automatically,(非空数据类型),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63985741/