You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
151 lines
3.6 KiB
Markdown
151 lines
3.6 KiB
Markdown
# Model validation & API Design
|
|
|
|
# Model Validation
|
|
|
|
ASP.NET has a built-in system for validating whether the data sent in requests fits the model set in the code
|
|
|
|
Additional requirements can be set with attributes
|
|
|
|
public class Contact
|
|
|
|
{
|
|
|
|
public int Id { get; set; }
|
|
|
|
[Required]
|
|
|
|
[MaxLength(50)]
|
|
|
|
public string Name { get; set; }
|
|
|
|
[MaxLength(100)]
|
|
|
|
public string Email { get; set; }
|
|
|
|
}
|
|
|
|
# Model Validation (continued)
|
|
|
|
An object can be validated at any time with TryValidateModel method:
|
|
|
|
[HttpPost]
|
|
|
|
public IActionResult Post([FromBody] Contact contact)
|
|
|
|
{
|
|
|
|
if (!TryValidateModel(contact))
|
|
|
|
{
|
|
|
|
return BadRequest(ModelState);
|
|
|
|
}
|
|
|
|
Contacts.Add(contact);
|
|
|
|
return Created(Request.Path, contact);
|
|
|
|
}
|
|
|
|
The attributes set a corresponding error message and information to the ModelState which is sent with the bad request result
|
|
|
|

|
|
|
|

|
|
|
|
Sometimes you might have custom requirements and the action should, according to the standard, return a bad request if the action does not fit those requirements
|
|
|
|
For example, the simplest possible way to validate the format of an email is to check whether it contains the '@' symbol and with AddModelError add an error if it does not:
|
|
|
|
if (!contact.Email.Contains('@'))
|
|
|
|
{
|
|
|
|
ModelState.AddModelError("Description", "The email is not in valid form.");
|
|
|
|
}
|
|
|
|
Then check the model state:
|
|
|
|
if (!ModelState.IsValid)
|
|
|
|
{
|
|
|
|
return BadRequest(ModelState);
|
|
|
|
}
|
|
|
|
# Exercise 1:
|
|
|
|
Continue working on CourseAPI.
|
|
|
|
Mark all the properties of the Course class with the [Required] attribute
|
|
|
|
Create an endpoint for POST requests with the URI api/courses
|
|
|
|
All the contents of the new course should come from the request body and the new course should be added to the Courses list
|
|
|
|
The maximum number of credits should be 20 and minimun 1 (Tip: Range)
|
|
|
|
Return an appropriate response
|
|
|
|
# Model Validation - Limiting PATCH
|
|
|
|
* If we only want to allow the PATCH operation to affect Name and Email properties of Contact class
|
|
* Begin by declaring a class with only those fields:
|
|
* public class ContactPatch
|
|
* {
|
|
* public string Name { get; set; }
|
|
* public string Email { get; set; }
|
|
* }
|
|
|
|
# Model Validation - Limiting PATCH (continued)
|
|
|
|
Use the ContactPatch class instead of the actual class for patching:
|
|
|
|
[HttpPatch("{id}")]
|
|
|
|
public IActionResult Patch(int id, [FromBody] JsonPatchDocument<ContactPatch> patchDocument)
|
|
|
|
{
|
|
|
|
Contact initialContact = _contactRepository.GetContact(id);
|
|
|
|
ContactPatch patchContact = new ContactPatch
|
|
|
|
{ Name = initialContact.Name, Email = initialContact.Email };
|
|
|
|
patchDocument.ApplyTo(patchContact, ModelState);
|
|
|
|
if (!ModelState.IsValid)
|
|
|
|
{
|
|
|
|
return BadRequest();
|
|
|
|
}
|
|
|
|
initialContact.Name = patchContact.Name;
|
|
|
|
initialContact.Email = patchContact.Email;
|
|
|
|
_contactRepository.UpdateContact(id, initialContact);
|
|
|
|
return Ok(initialContact);
|
|
|
|
}
|
|
|
|
# Designing APIs
|
|
|
|
It's useful to get a good overview of the API for yourself and others before getting to work
|
|
|
|
| __Method__ | __Endpoint__ | __Description__ | __Success__ | __Failure__ |
|
|
| :-: | :-: | :-: | :-: | :-: |
|
|
| __GET__ | __/api/contacts__ | __Return all contacts__ | __200 Ok__ | __400 Bad request__ __404 Not found__ |
|
|
| __POST__ | __/api/contacts__ | __Add a new contact__ | __201 Created__ | __400 Bad request__ |
|
|
| __PUT__ | __/api/contacts/{id}__ | __Update a contact__ | __204 No content__ | __400 Bad request__ __404 Not found__ |
|
|
| __PATCH__ | __/api/contacts/{id}__ | __Partially update a contact__ | __204 No content__ | __400 Bad request__ __404 Not found__ |
|
|
| __DELETE__ | __/api/contacts/{id}__ | __Remove a contact__ | __200 OK__ | __404 Not found__ |
|
|
|