3

次のリクエストを 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."
        ]
    }
}

ご覧のとおり、車に関する追加のエラー メッセージが 1 つありますJsonMediaTypeFormatter。同様に検証を実行し、読み取りアクションの実行に失敗していると推測しています。

これはここの問題ですか?JsonMediaTypeFormatter レベルで検証を抑制する方法はありますか? IBodyModelValidatorフォーマッタがメッセージ本文を読み取った後に検証も実行されるため、フォーマッタに検証を実行させたくありません。

編集:

ソース コードをデバッグしたところ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);
}

私はまだこの行動を抑えることができません。

4

2 に答える 2

3

申し訳ありませんが、最初にあなたの質問を誤解しました。OKここであなたがする必要があることです:

オリジナルから派生したクラスを作成し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ここで、デフォルトをカスタマイズされたものに置き換えてください。

于 2012-09-17T12:57:09.677 に答える
0

これは古い質問であることはわかっていますが、他の誰かが興味を持っている場合は、 [IsNotEmpty] 注釈を作成することでこれを回避できました。

これは、リフレクションを使用して、プロパティに Empty の実装があるかどうかを判断し、ある場合はそれを比較します。これは、JSON が解析されているときではなく、モデルの検証時に取得されます。

public class IsNotEmptyAttribute : ValidationAttribute
{

    public override bool IsValid(object value)
    {

        if (value == null) return false;

        var valueType = value.GetType();
        var emptyField = valueType.GetField("Empty");

        if (emptyField == null) return true;

        var emptyValue = emptyField.GetValue(null);

        return !value.Equals(emptyValue);

    }
}
于 2016-11-16T12:28:27.893 に答える