微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Net Core:对于非空数据类型,自动在Request API中强制要求的类成员

如何解决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 举报,一经查实,本站将立刻删除。