Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@
</Attribute>
</Attributes>
<Docs>
<summary>To be added.</summary>
<summary>
<para>Base class for validation attributes that require asynchronous operations, such as database lookups or API calls.</para>
<para>Derived implementations must be thread-safe, as instances of this attribute may be invoked concurrently from multiple threads.</para>
</summary>
<remarks>To be added.</remarks>
</Docs>
<Members>
Expand All @@ -37,7 +40,7 @@
</AssemblyInfo>
<Parameters />
<Docs>
<summary>To be added.</summary>
<summary>Default constructor for any async validation attribute.</summary>
<remarks>To be added.</remarks>
</Docs>
</Member>
Expand All @@ -57,8 +60,10 @@
<Parameter Name="errorMessageAccessor" Type="System.Func&lt;System.String&gt;" />
</Parameters>
<Docs>
<param name="errorMessageAccessor">To be added.</param>
<summary>To be added.</summary>
<param name="errorMessageAccessor">The <see cref="T:System.Func`1" /> that will return an error message.</param>
<summary>
<para>Allows for providing a resource accessor function that will be used by the <see cref="P:System.ComponentModel.DataAnnotations.ValidationAttribute.ErrorMessageString" /> property to retrieve the error message.</para>
</summary>
<remarks>To be added.</remarks>
</Docs>
</Member>
Expand All @@ -78,8 +83,8 @@
<Parameter Name="errorMessage" Type="System.String" />
</Parameters>
<Docs>
<param name="errorMessage">To be added.</param>
<summary>To be added.</summary>
<param name="errorMessage">A non-localized error message to use in <see cref="P:System.ComponentModel.DataAnnotations.ValidationAttribute.ErrorMessageString" />.</param>
<summary>Constructor that accepts a fixed validation error message.</summary>
<remarks>To be added.</remarks>
</Docs>
</Member>
Expand Down Expand Up @@ -116,12 +121,34 @@
<Parameter Name="cancellationToken" Type="System.Threading.CancellationToken" />
</Parameters>
<Docs>
<param name="value">To be added.</param>
<param name="validationContext">To be added.</param>
<param name="cancellationToken">To be added.</param>
<summary>To be added.</summary>
<returns>To be added.</returns>
<remarks>To be added.</remarks>
<param name="value">The value to validate.</param>
<param name="validationContext">
<para>A <see cref="T:System.ComponentModel.DataAnnotations.ValidationContext" /> instance that provides context about the validation operation, such as the object and member being validated. Provides access to services required to perform validation using <see cref="T:System.IServiceProvider" />.</para>
</param>
<param name="cancellationToken">A <see cref="T:System.Threading.CancellationToken" /> to observe while waiting for the task to complete.</param>
<summary>
<para>Tests whether the given <paramref name="value" /> is valid asynchronously with respect to the current validation attribute without throwing a <see cref="T:System.ComponentModel.DataAnnotations.ValidationException" />.</para>
</summary>
<returns>
<para>A <see cref="T:System.Threading.Tasks.Task`1" /> representing the asynchronous validation operation.</para>
<para>When validation is valid, the result is <see cref="F:System.ComponentModel.DataAnnotations.ValidationResult.Success" />.</para>
<para>When validation is invalid, the result is an instance of <see cref="T:System.ComponentModel.DataAnnotations.ValidationResult" />.</para>
</returns>
<remarks>
<para>
The underlying <see cref="M:System.ComponentModel.DataAnnotations.AsyncValidationAttribute.IsValidAsync(System.Object,System.ComponentModel.DataAnnotations.ValidationContext,System.Threading.CancellationToken)" /> implementation
must observe the supplied <paramref name="cancellationToken" /> and stop work promptly when cancellation
is requested. The validation infrastructure awaits all started validation tasks before returning, so an
implementation that ignores cancellation can delay failure and short-circuiting.
</para>
<para>
Callers that need to bound validation time should pass a token configured to cancel after a timeout,
such as one from a <see cref="T:System.Threading.CancellationTokenSource" /> configured with
<see cref="M:System.Threading.CancellationTokenSource.CancelAfter(System.TimeSpan)" />.
</para>
</remarks>
<exception cref="T:System.InvalidOperationException">is thrown if the current attribute is malformed.</exception>
<exception cref="T:System.ArgumentNullException">When <paramref name="validationContext" /> is <see langword="null" />.</exception>
</Docs>
</Member>
<Member MemberName="IsValid">
Expand All @@ -143,9 +170,12 @@
<Parameter Name="value" Type="System.Object" />
</Parameters>
<Docs>
<param name="value">To be added.</param>
<summary>To be added.</summary>
<returns>To be added.</returns>
<param name="value">The value to validate.</param>
<summary>
<para>Sealed override of <see cref="M:System.ComponentModel.DataAnnotations.ValidationAttribute.IsValid(System.Object)" /> that delegates to the <see cref="T:System.ComponentModel.DataAnnotations.ValidationContext" /> overload so that <see cref="T:System.ComponentModel.DataAnnotations.AsyncValidationAttribute" /> implementations only need to provide a single synchronous fallback via <see cref="M:System.ComponentModel.DataAnnotations.ValidationAttribute.IsValid(System.Object,System.ComponentModel.DataAnnotations.ValidationContext)" />.</para>
</summary>
<returns>
<see langword="true" /> if the value is valid; otherwise, <see langword="false" />.</returns>
<remarks>To be added.</remarks>
</Docs>
</Member>
Expand Down Expand Up @@ -176,11 +206,37 @@
</Parameter>
</Parameters>
<Docs>
<param name="value">To be added.</param>
<param name="validationContext">To be added.</param>
<summary>To be added.</summary>
<returns>To be added.</returns>
<remarks>To be added.</remarks>
<param name="value">The value to validate.</param>
<param name="validationContext">
<para>A <see cref="T:System.ComponentModel.DataAnnotations.ValidationContext" /> instance that provides context about the validation operation, such as the object and member being validated. Provides access to services required to perform validation using <see cref="T:System.IServiceProvider" />.</para>
</param>
<summary>Defines the synchronous validation behavior for this attribute.</summary>
<returns>
<para>
<see cref="F:System.ComponentModel.DataAnnotations.ValidationResult.Success" /> when validation is valid.</para>
<para>An instance of <see cref="T:System.ComponentModel.DataAnnotations.ValidationResult" /> when validation is invalid.</para>
</returns>
<remarks>
<para>
Synchronous validation consumers invoke this method. Provide a synchronous implementation when
it can evaluate the applicable rule. Return a validation error when the rule rejects the value.
If an applicable, required rule cannot be evaluated synchronously, throw
<see cref="T:System.InvalidOperationException" /> with a message directing callers to an asynchronous
validation entry point. An unsupported invocation does not establish that the value is invalid.
</para>
<para>
Return <see cref="F:System.ComponentModel.DataAnnotations.ValidationResult.Success" /> without evaluating the rule only when the rule
does not apply, or when the synchronous pass is explicitly advisory and a separate, required
asynchronous validation step governs acceptance. Success does not indicate pending validation
or arrange a later asynchronous invocation. Do not return success merely because a required
asynchronous check cannot run.
</para>
<para>
Do not implement this method by blocking on asynchronous work, such as by using
<c>Task&lt;TResult&gt;.Result</c>, <c>Task.Wait()</c>, or <c>GetAwaiter().GetResult()</c>.
Wrapping the operation in <c>Task.Run</c> does not make a blocking wait appropriate.
</para>
</remarks>
</Docs>
</Member>
<Member MemberName="IsValidAsync">
Expand Down Expand Up @@ -217,12 +273,30 @@
<Parameter Name="cancellationToken" Type="System.Threading.CancellationToken" />
</Parameters>
<Docs>
<param name="value">To be added.</param>
<param name="validationContext">To be added.</param>
<param name="cancellationToken">To be added.</param>
<summary>To be added.</summary>
<returns>To be added.</returns>
<remarks>To be added.</remarks>
<param name="value">The value to validate.</param>
<param name="validationContext">
<para>A <see cref="T:System.ComponentModel.DataAnnotations.ValidationContext" /> instance that provides context about the validation operation, such as the object and member being validated. Provides access to services required to perform validation using <see cref="T:System.IServiceProvider" />.</para>
</param>
<param name="cancellationToken">A <see cref="T:System.Threading.CancellationToken" /> to observe while waiting for the task to complete.</param>
<summary>Override this method in subclasses to implement asynchronous validation logic.</summary>
<returns>
<para>A <see cref="T:System.Threading.Tasks.Task`1" /> representing the asynchronous validation operation.</para>
<para>When validation is valid, the result is <see cref="F:System.ComponentModel.DataAnnotations.ValidationResult.Success" />.</para>
<para>When validation is invalid, the result is an instance of <see cref="T:System.ComponentModel.DataAnnotations.ValidationResult" />.</para>
</returns>
<remarks>
<para>
This method must perform all applicable checks, including checks that can run synchronously.
The synchronous <see cref="M:System.ComponentModel.DataAnnotations.AsyncValidationAttribute.IsValid(System.Object,System.ComponentModel.DataAnnotations.ValidationContext)" /> implementation is not
automatically invoked before this method. Share common checks through a helper when needed.
</para>
<para>
Implementations must observe the supplied <paramref name="cancellationToken" /> and stop work promptly
when cancellation is requested. The validation infrastructure may cancel this token after a validation
failure to stop sibling validators and awaits all started validation tasks before returning. An
implementation that ignores cancellation can delay failure and short-circuiting.
</para>
</remarks>
</Docs>
</Member>
</Members>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,34 @@
</Interface>
</Interfaces>
<Docs>
<summary>To be added.</summary>
<remarks>To be added.</remarks>
<summary>Provides a way for an object to be validated asynchronously.</summary>
<remarks>
<para>
When an object implements <see cref="T:System.ComponentModel.DataAnnotations.IAsyncValidatableObject" />, the asynchronous
<see cref="T:System.ComponentModel.DataAnnotations.Validator" /> APIs (such as
<see cref="M:System.ComponentModel.DataAnnotations.Validator.TryValidateObjectAsync(System.Object,System.ComponentModel.DataAnnotations.ValidationContext,System.Collections.Generic.ICollection{System.ComponentModel.DataAnnotations.ValidationResult},System.Threading.CancellationToken)" />)
invoke only <see cref="M:System.ComponentModel.DataAnnotations.IAsyncValidatableObject.ValidateAsync(System.ComponentModel.DataAnnotations.ValidationContext,System.Threading.CancellationToken)" />; <see cref="M:System.ComponentModel.DataAnnotations.IValidatableObject.Validate(System.ComponentModel.DataAnnotations.ValidationContext)" />
is not called on the async path. The synchronous <see cref="T:System.ComponentModel.DataAnnotations.Validator" />
APIs continue to invoke <see cref="M:System.ComponentModel.DataAnnotations.IValidatableObject.Validate(System.ComponentModel.DataAnnotations.ValidationContext)" />.
</para>
<para>
Provide a synchronous implementation of <see cref="M:System.ComponentModel.DataAnnotations.IValidatableObject.Validate(System.ComponentModel.DataAnnotations.ValidationContext)" /> when it can
evaluate the applicable rules, returning validation errors for rules that reject the object.
If an applicable, required rule cannot be evaluated synchronously, throw
<see cref="T:System.InvalidOperationException" /> with a message directing callers to an asynchronous
validation entry point.
</para>
<para>
Returning no validation errors without evaluating a rule is appropriate only when the rule
does not apply, or when the synchronous pass is explicitly advisory and a separate, required
asynchronous validation step governs acceptance. An empty result sequence does not indicate
pending validation or arrange a later asynchronous invocation.
</para>
<para>
Do not implement <see cref="M:System.ComponentModel.DataAnnotations.IValidatableObject.Validate(System.ComponentModel.DataAnnotations.ValidationContext)" /> by blocking on asynchronous work
or asynchronously enumerated results.
</para>
</remarks>
</Docs>
<Members>
<Member MemberName="ValidateAsync">
Expand All @@ -38,11 +64,20 @@
<Parameter Name="cancellationToken" Type="System.Threading.CancellationToken" />
</Parameters>
<Docs>
<param name="validationContext">To be added.</param>
<param name="cancellationToken">To be added.</param>
<summary>To be added.</summary>
<returns>To be added.</returns>
<remarks>To be added.</remarks>
<param name="validationContext">
<para>A <see cref="T:System.ComponentModel.DataAnnotations.ValidationContext" /> instance that provides context about the validation operation, such as the object and member being validated.</para>
</param>
<param name="cancellationToken">A <see cref="T:System.Threading.CancellationToken" /> to observe while waiting for the task to complete.</param>
<summary>
<para>Determines whether the specified object is valid asynchronously, yielding validation results as each check completes.</para>
</summary>
<returns>
<para>An <see cref="T:System.Collections.Generic.IAsyncEnumerable`1" /> that yields <see cref="T:System.ComponentModel.DataAnnotations.ValidationResult" /> instances as each validation check completes.</para>
</returns>
<remarks>
<para>This method must perform all applicable checks, including checks that can run synchronously.</para>
<para>The asynchronous <see cref="T:System.ComponentModel.DataAnnotations.Validator" /> APIs do not automatically invoke <see cref="M:System.ComponentModel.DataAnnotations.IValidatableObject.Validate(System.ComponentModel.DataAnnotations.ValidationContext)" /> first. Share common checks through a helper when needed.</para>
Comment on lines +78 to +79
</remarks>
</Docs>
</Member>
</Members>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -532,7 +532,9 @@ This property is the error message that you associate with the validation contro
<summary>Gets a value that indicates whether the attribute requires validation context.</summary>
<value>
<see langword="true" /> if the attribute requires validation context; otherwise, <see langword="false" />.</value>
<remarks>To be added.</remarks>
<remarks>
<para>This property is a hint for callers deciding whether a <see cref="T:System.ComponentModel.DataAnnotations.ValidationContext" /> must be supplied. The asynchronous validation entry point <see cref="M:System.ComponentModel.DataAnnotations.AsyncValidationAttribute.GetValidationResultAsync(System.Object,System.ComponentModel.DataAnnotations.ValidationContext,System.Threading.CancellationToken)" /> always requires a non-<see langword="null" /> <see cref="T:System.ComponentModel.DataAnnotations.ValidationContext" /> parameter, so this property is not applicable to the asynchronous pipeline.</para>
</remarks>
</Docs>
</Member>
<MemberGroup MemberName="Validate">
Expand Down
21 changes: 15 additions & 6 deletions xml/System.ComponentModel.DataAnnotations/ValidationContext.xml
Original file line number Diff line number Diff line change
Expand Up @@ -436,12 +436,21 @@
<summary>Gets the dictionary of key/value pairs that is associated with this context.</summary>
<value>The dictionary of the key/value pairs for this context.</value>
<remarks>
<format type="text/markdown"><![CDATA[

## Remarks
This property is never `null`, but the dictionary can be empty. Changes made to items in this dictionary are reflected in the original dictionary that is specified in the constructor.

]]></format>
<para>
This property is never <see langword="null" />, but the dictionary can be empty.
Changes made to entries in this dictionary do not affect the original dictionary
specified in the constructor.
</para>
<para>
<see cref="P:System.ComponentModel.DataAnnotations.ValidationContext.Items" />
is designed as a read-only input channel populated before validation begins.
The validation pipeline does not guarantee attribute execution order beyond
<see cref="T:System.ComponentModel.DataAnnotations.RequiredAttribute" /> priority,
and no built-in attribute mutates this dictionary during validation.
Custom validators should treat it as read-only during validation execution.
Mutating it from within a validator is unsupported and can produce race
conditions under parallel asynchronous validation.
</para>
</remarks>
</Docs>
</Member>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@
<Docs>
<param name="message">A specified message that states the error.</param>
<summary>Initializes a new instance of the <see cref="T:System.ComponentModel.DataAnnotations.ValidationException" /> class using a specified error message.</summary>
<remarks>To be added.</remarks>
<remarks>The long form of this constructor is preferred because it gives better error reporting.</remarks>
</Docs>
</Member>
<Member MemberName=".ctor">
Expand Down
Loading
Loading