Problem
You want the ASP. NET Web API to perform model validation while sharing some validation logic with ASP.
Solution Solutions
Thesame authentication mechanism that the ASP. NET W eb API supports with ASP. NET MVC is validated by the System.ComponentModel.DataAnnoataions property. Using the relevant validation properties provided by the framework is sufficient to validate the model.
for finer granularity validation, we can choose to implement ivaludateobjectsystem.componentmodel.dataannotations). If all the properties are verified through, asp.net Web api validate method, where we can do a further physical validation. This is the same behavior as mvc web API mvc using the same Dto
Another way to do this is to use a third- Party library called fluentvalidation (which can download fluentvalidation in NuGet). He can build more powerful validation scenarios. In this case, we still need to implement the Ivalidateobject interface in our model and rely on the fluentvalidation Validator instead of the inline validation logic.
Tip : The authentication behavior of the ASP. NET Web API is the same across the host.
Working principle
In order to Read the model from the HTTP request Body and perform validation, the ASP. NetWeb API relies on a ibodymodelvalidator The service. The approximate description of the interface is shown in Listing 1-17, however, he is an alternative service, under normal circumstances, the default implementation (Defaultbodymodelvalidator) is sufficient forus to use, in the httpconfiguration is set to self-boot.
Listing 1-17. Ibodymodelvalidator interface
12345 |
public interface IBodyModelValidator { bool Validate( object model, Type type, ModelMetadataProvider metadataProvider, HttpActionContext actionContext, string keyPrefix); } |
has a service called formatrtparameterbinding http request body When processing requests bound to action parameters, Defaultbodymodelvalidator validate < The span lang= "ZH-CN" > method is called. For validators, he validates the entire object map recursively, validating each attribute and nested properties. web api by using dataannotationmodelvalidatorproviderr wcf datamemberattribute < Span lang= the "ZH-CN" > declaration, then we need to use the framework of the datamembervalidatorprovider
Finally, our model can implement the Ivalidatableobject interface, which exposes only a simple method as shown in Listing 1-18 . If the interface is implemented, then we need to provide additional validation logic for ourselves. TheASP. NET WWB API calls the Validate method of the Ivalidateableobject interface as long as all property validation passes.
Listing 1-18. Definition of the Ivalidateableobject interface
1234 |
public interface IValidateableObject { IEnumerable<ValidationResult> Validate(ValidationContext validationContext); } |
The results are verified by asp.net Web api < Span lang= "ZH-CN" >modelstatedictionary form, here modelstate asp.net mvc The concepts in are identical, but the objects used are different because web api system.web.http.modelbindingmodelstatedictionary exposed Isvalid action model Verify the status.
The validation mechanism of the
declaration is also well integrated into asp.net Web API Help Page api semantic description. We will discuss him in detail when 7-11
Tip in the API the best practice is to use different models as Request and Response entities. For example, the entity ID is generally only required by the Response model and can be obtained from the URI if required in the request .
Code
Listing 1-19 shows a scenario in which a model has multiple validations:
RequiredAttribute,maxlengthattribute and
Rangeattribute. Next, we can use modelstate to verify The validation state in the Controller and respond to the appropriate prompt to the caller.
Listing 1-19. Simple WEB API Model validation
123456789101112131415161718192021222324 |
public
class
Album
{
public int
Id {
get
;
set
; }
[Required(ErrorMessage =
"{0} is required"
)]
[MaxLength(30)]
public
string
Artist {
get
;
set
; }
[Required(ErrorMessage =
"{0} is required"
)]
[MaxLength(40)]
public
string
Title {
get
;
set
; }
[Range(0, 10, ErrorMessage =
"{0} in the range of {1}-{2} is required."
)]
public
int
Rating {
get
;
set
; }
}
public
class
AlbumController : ApiController
{
public
HttpResponseMessage Post(Album album)
{
if
(!ModelState.IsValid)
{
throw
new
HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.BadRequest,
ModelState));
}
//omitted for brevity
}
}
|
The general validation that handles the Modelstate code can easily be extracted from the Controller into a common part that can be reused well, but this part will be described in detail in 5-4 .
Now, let's consider this scenario, if we want to add two additional attributes Rating and starred to the model , while extending the model validation, the requirement for validation is that at least one of these two properties is required. Although the validation of entanglement between the two attributes is difficult to express in a declarative way, don't forget that ivalidateableobject can help us. We can use the Validata method in the interface to check the state of the entire model and return the corresponding Validationresult. The code we want to make is as shown in Listing 1-20.
Listing 1-20. Modifying the ASP. NET Web API relies on ivalidateableobject validation
1234567891011121314151617181920212223 |
public
class Album : IValidatableObject
{
public
int
Id {
get
;
set
; }
[Required(ErrorMessage =
"{0} is required"
)]
[MaxLength(30)]
public
string
Artist {
get
;
set
; }
[Required(ErrorMessage =
"{0} is required"
)]
[MaxLength(40)]
public
string
Title {
get
;
set
; }
public
int
? Rating {
get
;
set
; }
public
bool
? Starred {
get
;
set
; }
public
IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if
(!(Rating.HasValue && Rating > 0 && Rating < 10) || (Starred.HasValue && Starred.Value))
{
yield
return
new
ValidationResult(
"You must set either the Rating in the 0-9 range orStarred flag."
);
}
}
}
|
[Boiled ASP. NET Web API2 methodology] (1-6) Model Validation