如何解决Net Core:对于非空数据类型,自动在Request API中强制要求的类成员
我们有API控制器,可通过请求Dto获取产品数据。为了使类成员成为必需,我们需要在Dto中放置<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<!-- MyAd -->
<ins class="adsbygoogle"
style="display:inline-block;width:320px;height:60px"
data-ad-client="xxxxxxxxx"
data-ad-slot="xxxxxxxx"></ins>
<script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>
属性。否则,服务可以使用空成员执行。
https://docs.microsoft.com/en-us/aspnet/core/mvc/models/validation?view=aspnetcore-3.1
当前拥有20个以上成员的Request DTO,并且在所有类成员中写required
似乎很重复。
我的问题是,为什么requiredAttribute是必需的?我们已经有int和nullable成员。数据类型本身不应该执行合同吗?
有没有一种方法可以使类成员自动化并强制执行required,而无需到处编写?
[required]
How to add custom error message with “required” htmlattribute to mvc 5 razor view text input editor
[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; }
....
解决方法
如果您愿意使用 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,string>();
}
//Other stuff...
}
}
}
}
NotEmpty
拒绝null和默认值。
Program.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);
}
}
}
}
输出:
名称:MyProperty1,类型:System.String
名称:MyProperty2,类型:System.Int32
名称:MyProperty3,类型:System.String
名称:MyProperty4,类型:System.Int32
不能为空。
不能为空。
不能为空。
不能为空。
完成!
还有一个更完整的解决方案: 请参见此问题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...
});
}
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。