ASP.NET Core [Require]非空类型 [英] ASP.NET Core [Require] non-nullable types

查看:528
本文介绍了ASP.NET Core [Require]非空类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

此处,提出了一个问题,即如何验证非空值是否必需类型.

Here, the question was posed how to validate non-nullable required types.

在我的情况下,不希望使用提供的使字段为空的解决方案,如下所示.

The provided solution to make the field nullable like the following is not desirable in my case.

[Required]
public int? Data { get; set; }

在请求中省略该字段的情况下,如何更改行为以进行以下失败验证.

How can you change the behavior to instead make the following fail validation in the cases where the field is omitted from the request.

[Required]
public int Data { get; set; }

我尝试了一个自定义验证器,但是这些没有原始值的信息,只能看到默认的0值.我也尝试过自定义模型绑定程序,但它似乎可以在整个请求模型的级别上工作,而不是在所需的整数字段上工作.我的资料夹实验看起来像这样:

I have tried a custom validator, but these do not have information about the raw value and only see the default 0 value. I have also tried a custom model binder but it seems to work at the level of the entire request model instead of the integer fields which a want. My binder experiment looks like this:

public class RequiredIntBinder : IModelBinder
{
    public Task BindModelAsync(ModelBindingContext bindingContext)
    {
        if (bindingContext.ModelType != typeof(int))
            throw new InvalidOperationException($"{nameof(RequiredIntBinder)} can only be applied to integer properties");

        var value = bindingContext.ValueProvider.GetValue(bindingContext.BinderModelName);
        if (value == ValueProviderResult.None)
        {
            bindingContext.Result = ModelBindingResult.Failed();
            return Task.CompletedTask;
        }

        return new SimpleTypeModelBinder(bindingContext.ModelType).BindModelAsync(bindingContext);
    }
}

public class RequiredIntBinderProvider : IModelBinderProvider
{
    public IModelBinder GetBinder(ModelBinderProviderContext context)
    {
        if (context == null)
        {
            throw new ArgumentNullException(nameof(context));
        }

        if (context.Metadata.ModelType == typeof(int))
        {
            return new BinderTypeModelBinder(typeof(RequiredIntBinder));
        }

        return null;
    }
}

并在这样的mvc中注册

and is registered with mvc like this

options.ModelBinderProviders.Insert(0, new RequiredIntBinderProvider());

,但从不使用模型联编程序.我觉得我可能很近,但是无法连接最后一个点.

but the model binder is never used. I feel like I might be close but cannot connect the last dots.

推荐答案

解决json请求的解决方案

无法验证已经创建的模型实例,因为不可为空的属性始终具有一个值(无论它是从json分配还是默认值). 解决方案是报告反序列化过程中已经丢失的值.

Solution working with json requests

You cannot validate an already created model instance, because a non-nullable property has always a value (no matter whether it was assigned from json or is a default value). The solution is to report the missing value already during deserialization.

创建合同解析器

public class RequiredPropertiesContractResolver : DefaultContractResolver
{
    protected override JsonObjectContract CreateObjectContract(Type objectType)
    {
        var contract = base.CreateObjectContract(objectType);

        foreach (var contractProperty in contract.Properties)
        {
            if (contractProperty.PropertyType.IsValueType
                && contractProperty.AttributeProvider.GetAttributes(typeof(RequiredAttribute), inherit: true).Any())
            {
                contractProperty.Required = Required.Always;
            }
        }

        return contract;
    }
}

,然后将其分配给SerializerSettings:

services.AddMvc()
        .AddJsonOptions(jsonOptions =>
        {
            jsonOptions.SerializerSettings.ContractResolver = new RequiredPropertiesContractResolver();
        });

如果json中缺少值,则ModelState对于具有[Required]属性的不可为null的属性无效.

The ModelState is then invalid for non-nullable properties with the [Required] attribute if the value is missing from json.

Json身体

var jsonBody = @"{ Data2=123 }"

对于模型无效

class Model
{
    [Required]
    public int Data { get; set; }

    public int Data2 { get; set; }
}

这篇关于ASP.NET Core [Require]非空类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆