Mam klasy DTO, który wygląda na przykład tak:.NET Web: atrybut walidacja poziomie klasy powoduje Web API rzucać ArgumentNullException jeśli instancja jest równa null
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; }
}
Jeśli, jako przykład, użytkownik wprowadzi nieprawidłową datę, takie jak ten:
<?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>
lub po prostu pusty korpus, a następnie argument ExampleDto przeszedł do działania będzie zerowa (w pierwszym przypadku ModelState będą miały błędy).
I zastosował CustomValidationAttribute do klasy, więc deklaracja klasy wygląda następująco:
[CustomValidation(typeof(CustomExampleValidator), "Validate")]
public class ExampleDto
Teraz dodałem to, jeśli argument ExampleDto jest zerowy (z powodu pustego ciała, lub problem serializacji), ArgumentNullException jest wyrzucany:
<?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.<>c__DisplayClass1.<ExecuteBindingAsync>b__0(Object
model) at System.Threading.Tasks.TaskHelpersExtensions.<>c__DisplayClass36`1.<>c__DisplayClass38.<Then>b__35()
at System.Threading.Tasks.TaskHelpersExtensions.<>c__DisplayClass49.<ToAsyncVoidTask>b__48()
at System.Threading.Tasks.TaskHelpers.RunSynchronously[TResult](Func`1
func, CancellationToken cancellationToken)</StackTrace>
</Error>
</Errors>
</Response>
Reflektor pokazuje, że zerowa kontrola wykonywana jest argumentem przeciwko obiektu w konstruktora ValidationContext, tuż przed CustomValidationAttribute jest wykonywany. Wydaje się to trochę dziwne, ponieważ argumenty zerowe są akceptowane jako argumenty dla działań kontrolerów, nie? Myślę, że wszelkie tutaj zerowe sprawdzanie argumentów POWINNO być wykonywane w kodzie użytkownika lub jawnie przez atrybuty sprawdzania poprawności, zamiast przez framework.
Jeśli użytkownik przesyła prawidłowy kod XML/JSON, ten wyjątek nie jest generowany, a parametr CustomValidationAttribute jest wykonywany zgodnie z oczekiwaniami, ale użytkownicy nie zawsze mogą być zaufani, aby przesłać poprawny plik XML/JSON, a także uzyskać rozwlekły wygląd ArgumentNullException za ich wysiłki, zamiast za to, że jestem w stanie się zwrócić.
Staram się znaleźć kogoś, kto tego doświadczył. Istnieje wiele przykładów zastosowania walidatorów "złożonych" na poziomie właściwości, ale bardziej sensowne jest dla mnie zastosowanie tutaj walidacji na poziomie klasy (ponieważ wymagane są różne właściwości, JEŚLI konkretna właściwość nie jest pusta, a inne są wymagane, JEŻELI inna właściwość nie jest pusta) i nie mogę znaleźć niczego, co mogłoby powiedzieć, że atrybuty sprawdzania poprawności zastosowane na poziomie klasy są nieobsługiwane.
jako obejście, Wprowadziłem jawnie IValidatableObject, aby wykonać walidację. Wolę jednak używać atrybutów sprawdzania poprawności, więc nadal szukam wyjaśnienia. –
Próbowałem powtórzyć Twój problem, ale bez powodzenia ... Spójrz na to zdjęcie: http://tallmaris.com/blog/wp-content/uploads/2013/06/Capture.png. Jak widać wartość dotarła do walidatora i nie jest pusta. Gdy dojdzie do kontrolera, 'IsValid' będzie fałszywe z powodu daty oczywiście. Opublikowane informacje dotyczące tego wyniku to: 'var example = new {Chi =" YYY ", PatientStatus = 1, Date =" 2012-05-25T18: 23: XXXX ", ParentExample =" B62F10A8-4998-4626-B5B0-4B9118E11BEC "};' (następnie Json serializował i przesyłał). – Tallmaris
Witaj Tallmaris, dziękuję za oddanie. Wyjątek nie zostanie zgłoszony, jeśli wartość nie jest pusta, tylko jeśli ma wartość NULL.Spróbuj wysłać z var example = null ;, lub przesłać json ręcznie i z błędem składni w nim. –