6

たとえば、次のような 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 になります (前者の場合、ModelState にエラーが発生します)。

クラスに CustomValidationAttribute を適用したので、クラス宣言は次のようになります。

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

これを追加したので、ExampleDto 引数が 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>

Reflector は、CustomValidationAttribute が実行される直前に、ValidationContext のコンストラクターでオブジェクトに対して null 引数チェックが実行されることを示しています。null 引数はコントローラー アクションの引数として受け入れられるため、これは少し奇妙に思えます。ここでのnull引数チェックは、フレームワークではなく、ユーザーコードで、または検証属性によって明示的に実行する必要があると思います。

ユーザーが正しい XML/JSON を送信した場合、この例外はスローされず、CustomValidationAttribute は期待どおりに実行されますが、ユーザーが正しい XML/JSON を送信することを常に信頼できるとは限りません。私が自分自身を返すことができるものの代わりに。

これを経験した人を他に見つけるのに苦労しています。プロパティ レベルで「複合」バリデータを適用する例はたくさんありますが、ここではクラス レベルで検証を適用する方が理にかなっています (特定のプロパティが null でない場合は複数のプロパティが必要であり、ある場合は他のプロパティが必要になるためです)。別のプロパティはnullではありません)、クラスレベルで適用される検証属性がサポートされていないと言うことは何も見つかりません.

4

1 に答える 1