使用Filter和ValidatorAttribute导致ValidationContext的c。中的System.ArgumentNullException

问题描述 投票:1回答:1

我有一个ASP WebAPI项目,我想使用自定义的validateator属性在我的api中进行一些特殊的验证。为此,我在api中添加了一个过滤器(目前还没有什么特别的):

public class LogFilter : ActionFilterAttribute
{
    public LogFilter()
    {

    }

    public override void OnActionExecuting(HttpActionContext ActionContext)
    {
        Trace.WriteLine(string.Format("Action Method {0} executing at {1}", ActionContext.ActionDescriptor.ActionName, DateTime.Now.ToShortDateString()), "Web API Logs");

        if (ActionContext.ModelState.IsValid == false)
        {
            ActionContext.Response = ActionContext.Request.CreateErrorResponse(
                HttpStatusCode.BadRequest, ActionContext.ModelState);
        }
    }

    public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
    {
        Trace.WriteLine(string.Format("Action Method {0} executed at {1}", actionExecutedContext.ActionContext.ActionDescriptor.ActionName, DateTime.Now.ToShortDateString()), "Web API Logs");
    }
}

下一步我要做的是创建一个新的ValidatorAttribute,称为GroupValidatorAttribute(目前尚无特殊实现,这只是一个演示我的问题的最小工作示例):

[AttributeUsage(AttributeTargets.Class)]
public class GroupValidatorAttribute : ValidationAttribute
{

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        if (value == null)
        {
            return new ValidationResult("" + validationContext.DisplayName + " cant be null");
        }

        return ValidationResult.Success;
    }
}

因此,最后,我们需要使用GroupValidator属性的模型类:

[GroupValidator]
public class Student
{
    public int? Age { get; set; }
    public string name { get; set; }
}

肯定还有一个控制器,该控制器的端点类型为post,应从主体获取班级学生(我的模型)的对象:

    [HttpPost]
    [Route("Body")]
    public HttpResponseMessage BodyTest(int id, [FromBody] Student student)
    {
        return Request.CreateResponse(HttpStatusCode.OK,
            "Suc");
    }

好的,到目前为止很好。它几乎达到了预期的效果,但是有一个案例使我发疯。如果我将一个空的正文发送(发布)到api中的终结点,则会发生System.ArgumentNullException。

这是完全例外:

“ ExceptionMessage”:“ Der Wert darn nic se NULL。\ r \ n参数名:instance”,“ ExceptionType”:“ System.ArgumentNullException”,“ StackTrace”:“ bei System.ComponentModel.DataAnnotations.ValidationContext..ctor(对象实例,IServiceProvider serviceProvider,IDictionary2 items)\r\n bei System.Web.Http.Validation.Validators.DataAnnotationsModelValidator.Validate(ModelMetadata metadata, Object container)\r\n bei System.Web.Http.Validation.DefaultBodyModelValidator.ShallowValidate(ModelMetadata metadata, BodyModelValidatorContext validationContext, Object container, IEnumerable1验证程序)\ r \ n bei System.Web.Http.Validation.DefaultBodyModelValidator.ValidateNodeAndChildren(ModelMetadata元数据, BodyModelValidatorContextvalidationContext,对象容器,IEnumerable`1验证程序)\ r \ n在System.Web.Http.Validation.DefaultBodyModelValidator.Validate(对象模型,类型类型,ModelMetadataProvider元数据提供程序,HttpActionContext actionContext,字符串keyPrefix)\ r \ n北系统中。 Web.Http.ModelBinding.FormatterParameterBinding.d__18.MoveNext()\ r \ n --- Ende derStapelüberwachungvom vorhergehenden Ort,Des die Ausnahmeausgelöstwurde --- \ r \ n bei System.Runtime.Compilerucs.TaskAwaiter.ThrowForNonS (任务任务)\ r \ n是System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务)\ r \ n是System.Web.Http.Controllers.HttpActionBinding.d__12.MoveNext()\ r \ n- -Ende derStapelüberwachungvom vorhergehenden Ort,一名来自澳大利亚的人--- \ r \ n在System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务任务)\ r \ n bei System.Runtime.CompilerServiceAnd.Noton (任务任务)\ r \ n System.Web.Http.Controllers.ActionFilterResult.d__5.MoveNext()\ r \ n --- Ende derStapelüberwachungvor vorhergehenden Ort,Dem die Ausnahmeausgelöstwurde --- \ r \ n bei System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务任务)\ r \ n bei System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务)\ r \ n bei System.Web.Http.Dispatcher.HttpControllerDispatcher.d__15。 MoveNext()“

在调试器中,我看到过滤器中的方法和验证器中的方法未命中。有人可以帮助我吗?

c# api asp.net-web-api
1个回答
0
投票

ArgumentNullException("instance")异常是从ValidationContext的构造函数生成的,因为在您的情况下instance为null。

ValidationContext的构造函数的代码片段:Source code

public ValidationContext(object instance, IServiceProvider serviceProvider,
                         IDictionary<object, object> items) 
{
    if (instance == null) {
       throw new ArgumentNullException("instance");
    }
    ....

现在,您的问题是:在调试器中,我可以看到我的过滤器和验证器中的方法未命中。

调用堆栈类似于

DataAnnotationsModelValidator.Validate() ->
            DataAnnotations.ValidationAttribute.GetValidationResult() ->
            GroupValidatorAttribute.IsValid() 

ValidationContext的构造函数是在Validate()阶段创建的(引发null异常),但是只有在已经执行IsValid()检查之后才调用null的实现。因此,IsValid()永远不会打到您的案子。

© www.soinside.com 2019 - 2024. All rights reserved.