编程语言
首页 > 编程语言> > 禁止在ASP.NET Web API中对JsonMediaTypeFormatter进行RequiredAttribute验证

禁止在ASP.NET Web API中对JsonMediaTypeFormatter进行RequiredAttribute验证

作者:互联网

假设我向API发送了以下请求:

POST http://localhost:4940/api/cars HTTP/1.1
User-Agent: Fiddler
Host: localhost:4940
Content-Type: application/json
Content-Length: 44

{"Make":"Make1","Year":2010,"Price":10732.2}

而且我有以下Car类定义:

public class Car {

    public int Id { get; set; }

    [Required]
    [StringLength(20)]
    public string Make { get; set; }

    [Required]
    [StringLength(20)]
    public string Model { get; set; }

    public int Year { get; set; }

    [Range(0, 500000)]
    public float Price { get; set; }
}

我得到的回复如下:

HTTP/1.1 400 Bad Request
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/json; charset=utf-8
Expires: -1
Server: Microsoft-IIS/8.0
X-AspNet-Version: 4.0.30319
X-SourceFiles: =?UTF-8?B?RTpcRHJvcGJveFxCb29rc1xQcm9XZWJBUEkuU2FtcGxlc1xDaGFwdGVyMTNcRGF0YUFubm90YXRpb25WYWxpZGF0aW9uQXR0cmlidXRlc1NhbXBsZVxEYXRhQW5ub3RhdGlvblZhbGlkYXRpb25BdHRyaWJ1dGVzU2FtcGxlXGFwaVxjYXJz?=
X-Powered-By: ASP.NET
Date: Mon, 17 Sep 2012 11:38:58 GMT
Content-Length: 182

{"Message":"The request is invalid.","ModelState":{"car":["Required property 'Model' not found in JSON. Path '', line 1, position 44."],"car.Model":["The Model field is required."]}}

这是消息正文的更易读的形式:

{
    "Message": "The request is invalid.",
    "ModelState": {
        "car": [
            "Required property 'Model' not found in JSON. Path '', line 1, position 44."
        ],
        "car.Model":[
            "The Model field is required."
        ]
    }
}

如您所见,我还有一条关于汽车的错误消息,我猜JsonMediaTypeFormatter也执行验证,并且它无法执行读取动作.

这是这里的问题吗?有什么方法可以抑制JsonMediaTypeFormatter级别的验证?我不希望格式化程序执行验证,因为在格式化程序读取消息正文之后,验证也由IBodyModelValidator执行.

编辑:

我调试了源代码,并且如果将Property标记为Required且未提供,它会淘汰JsonMediaTypeFormatter引发错误.以下代码是JsonMediaTypeFormatter的一部分:

// Error must always be marked as handled
// Failure to do so can cause the exception to be rethrown at every recursive level and overflow the stack for x64 CLR processes
jsonSerializer.Error += (sender, e) =>
{
    Exception exception = e.ErrorContext.Error;
    formatterLogger.LogError(e.ErrorContext.Path, exception);
    e.ErrorContext.Handled = true;
}

并触发ModelStateFormatterLogger.LogError方法,该方法将错误放入ModelState中:

public void LogError(string errorPath, Exception exception)
{
    if (errorPath == null)
    {
        throw Error.ArgumentNull("errorPath");
    }
    if (exception == null)
    {
        throw Error.ArgumentNull("exception");
    }

    string key = ModelBindingHelper.ConcatenateKeys(_prefix, errorPath);
    _modelState.AddModelError(key, exception);
}

我仍然无法抑制这种行为.

解决方法:

对不起,我原本误解了你的问题.
确定,这是您需要做的:

创建一个从原始JsonMediaTypeFormatter派生的类,并设置一个自定义IRequiredMemberSelector

public class MyJsonMediaTypeFormatter : JsonMediaTypeFormatter
    {
        public MyJsonMediaTypeFormatter() : base()
        {
            RequiredMemberSelector = new MyRequiredMemberSelector();
        }
    }

在此自定义IRequiredMemberSelector中,只需定义所有不需要的属性.

public class MyRequiredMemberSelector : IRequiredMemberSelector
{
    public bool IsRequiredMember(System.Reflection.MemberInfo member)
    {
        return false;
    }
}

现在,将默认的JsonMediaTypeFormatter替换为自定义的JsonMediaTypeFormatter,然后开始.

标签:asp-net-web-api,json-net,data-annotations,c
来源: https://codeday.me/bug/20191127/2075682.html