.NET Web API:类级验证属性会导致Web API抛出ArgumentNulLexception(如果实例为null)[英] .NET Web API: Class level validation attribute causes Web API to throw ArgumentNullException if instance is null

本文是小编为大家收集整理的关于.NET Web API:类级验证属性会导致Web API抛出ArgumentNulLexception(如果实例为null)的处理方法,想解了.NET Web API:类级验证属性会导致Web API抛出ArgumentNulLexception(如果实例为null)的问题怎么解决?.NET Web API:类级验证属性会导致Web API抛出ArgumentNulLexception(如果实例为null)问题的解决办法?那么可以参考本文帮助大家快速定位并解决问题。

问题描述

我有一个dto类,看起来像这样:

public class ExampleDto
{
    [DataMember(Name = "Date", IsRequired = true, Order = 1), Required]
    public DateTime Date { get; set; }

    [DataMember(Name = "ParentExample", IsRequired = false, Order = 2, EmitDefaultValue = false)]
    public Guid? ParentExampleId { get; set; }
}

作为示例,用户提供了不正确的日期,例如:

<?xml version="1.0" encoding="UTF-8" ?>
<ExampleDto xmlns="http://customurl/">
       <Date>2012-05-25T18:23:INCORRECTDATE</Date>
       <ParentExample>B62F10A8-4998-4626-B5B0-4B9118E11BEC</ParentExample>
</ExampleDto>

或简单只是一个空的身体,然后传递到动作的exampledto参数将是null(在前一个情况下,模型符号将具有错误).

我向类应用了一个customvalidationAttribute,因此类声明如下所示:

[CustomValidation(typeof(CustomExampleValidator), "Validate")]
public class ExampleDto

现在我添加了这个,如果exam​​pledto参数为null(因为空体或序列化问题),则抛出ArgumentNulLexception:

<?xml version="1.0" encoding="UTF-8"?>
<Response xmlns="http://customurl" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
    <Type>Failure</Type>
    <Message>An unknown error has occurred</Message>
    <Errors>
        <Error>
            <Message>System.ArgumentNullException</Message>
            <MessageDetail>Value cannot be null. Parameter name:
                instance</MessageDetail>
            <StackTrace> at System.ComponentModel.DataAnnotations.ValidationContext..ctor(Object
                instance, IServiceProvider serviceProvider,
                IDictionary`2 items) at System.Web.Http.Validation.Validators.DataAnnotationsModelValidator.Validate(ModelMetadata
                metadata, Object container) at System.Web.Http.Validation.DefaultBodyModelValidator.ShallowValidate(ModelMetadata
                metadata, ValidationContext validationContext,
                Object container) at System.Web.Http.Validation.DefaultBodyModelValidator.ValidateNodeAndChildren(ModelMetadata
                metadata, ValidationContext validationContext,
                Object container) at System.Web.Http.Validation.DefaultBodyModelValidator.Validate(Object
                model, Type type, ModelMetadataProvider metadataProvider,
                HttpActionContext actionContext, String keyPrefix)
                at System.Web.Http.ModelBinding.FormatterParameterBinding.&lt;&gt;c__DisplayClass1.&lt;ExecuteBindingAsync&gt;b__0(Object
                model) at System.Threading.Tasks.TaskHelpersExtensions.&lt;&gt;c__DisplayClass36`1.&lt;&gt;c__DisplayClass38.&lt;Then&gt;b__35()
                at System.Threading.Tasks.TaskHelpersExtensions.&lt;&gt;c__DisplayClass49.&lt;ToAsyncVoidTask&gt;b__48()
                at System.Threading.Tasks.TaskHelpers.RunSynchronously[TResult](Func`1
                func, CancellationToken cancellationToken)</StackTrace>
        </Error>
    </Errors>
</Response>

反射器显示在执行CustomValidationAttribute之前,对validationContext的构造函数中的对象执行NULL参数检查.这似乎有点奇怪,因为null参数是控制器操作的参数可以接受,因为没有?我认为此处的任何NULL参数检查应在用户代码中或通过验证属性而不是框架明确地执行.

如果用户提交正确的XML/JSON,则不会抛出此异常,并且自定义ValidationAttribute按预期执行,但用户不能总是被信任提交正确的XML/JSON,并且可以获得看起来的ArgumentNulLException他们的努力,而不是我能够回归自己的​​努力.

我正在努力找到遇到过这个的别人.有大量的例子在物业级别应用"化合物"验证器,但它对我来说更有意义以在此处应用验证在类级别(因为如果特定属性未为空,则需要多个属性,并且如果a不同的属性不是null),我找不到任何可以说在类级别应用的验证属性不受支持.

推荐答案

我有同样的问题.遗憾的是,有很多验证了.因此,在释放之前,将所有它们重写为rivalidatableObject并不是可行的.所以我的快速和肮脏的解决方案是在过滤器中捕获这些例外,并发回适当的响应:

public class GeneralExceptionFilterAttribute : ExceptionFilterAttribute
{
   public override void OnException(HttpActionExecutedContext context)
   {
        var exceptionType = context.Exception.GetType();
        HttpResponseMessage response = null;

        if(exceptionType == typeof(ArgumentNullException)
            && context.Exception.StackTrace.TrimStart().StartsWith("at System.ComponentModel.DataAnnotations.ValidationContext..ctor"))
        {
            response = new HttpResponseMessage(HttpStatusCode.BadRequest)
            {
                Content = new StringContent(context.Exception.Message)
            };
        }
        else
        {
            response = new HttpResponseMessage(HttpStatusCode.InternalServerError)
            {
                Content = new StringContent(context.Exception.Message),
                ReasonPhrase = "Unhandled exception"
            };
        }

        context.Response = response;
        _errorLogger.LogError(response?.ReasonPhrase, context.Exception);
    }
}

并在webapiconfig.cs中全局注册文件管理器:

config.Filters.Add(new GeneralExceptionFilterAttribute());

本文地址:https://www.itbaoku.cn/post/1793770.html