Calling the API from a page to register the customer
To simplify things, I have designed a simple HTML page with controls for a customer record, as follows. We will input data and try to call the API in order to save the record:
<p class="container">
<h2>Register for FlixOneStore</h2>
<p class="form-horizontal">
<p class="form-group">
<label class="control-label col-sm-2" for=
"txtFirstName">First Name:</label>
<p class="col-sm-3">
<input type="text" class="form-control" id=
"txtFirstName" placeholder=
"Enter first name" name="firstname">
</p>
</p>
<p class="form-group">
<label class="control-label col-sm-2" for=
"txtLastName">Last Name:</label>
<p class="col-sm-3">
<input type="text" class="form-control" id=
"txtLastName" placeholder=
"Enter last name" name="lastname">
</p>
</p>
<p class="form-group">
<label class="control-label col-sm-2" for="txtEmail">
Email:</label>
<p class="col-sm-3">
<input type="email" class="form-control" id=
"txtEmail" placeholder=
"Enter email" name="email">
</p>
</p>
<p class="form-group">
<label class="control-label col-sm-2" for="gender">
Gender:</label>
<p class="col-sm-3">
<label class="radio-inline"><input type="radio"
value="M" name="gender">Male</label>
<lable class="radio-inline"><input type="radio"
value="F" name="gender">Female</lable>
</p>
</p>
<p class="form-group">
<label class="control-label col-sm-2" for="txtDob">
Date of Birth:</label>
<p class="col-sm-3">
<input type="date" class="form-control" id="txtDob" />
</p>
</p>
<p class="form-group">
<label class="control-label col-sm-2" for="txtMobile">
Mobile Number:</label>
<p class="col-sm-3">
<input type="text" class="form-control" id="txtMobile"
placeholder=
"Enter mobile number" />
</p>
</p>
<p class="form-group">
<label class="control-label col-sm-2" for="txtFax">Fax:</label>
<p class="col-sm-3">
<input type="text" class="form-control" id="txtFax"
placeholder="Enter fax" />
</p>
</p>
<p class="form-group">
<label class="control-label col-sm-2" for="txtPassword">
Password:</label>
<p class="col-sm-3">
<input type="password" class="form-control" id=
"txtPassword" placeholder=
"Enter password" name="pwd">
</p>
</p>
<p class="form-group">
<label class="control-label col-sm-2" for="txtConfirmPassword">
Confirm Password:</label>
<p class="col-sm-3">
<input type="password" class="form-control"
id="txtConfirmPassword" placeholder=
"Enter password again" name="confirmpwd">
</p>
</p>
<p class="form-group">
<p class="col-sm-offset-2 col-sm-10">
<button type="button" class="btn btn-success"
id="btnRegister">Register</button>
</p>
</p>
</p>
</p>
I have used bootstrap and jQuery with my code. You can refer to the whole code in the attached files with the book or refer to https://github.com/PacktPublishing/Building-RESTful-Web-services-with-DOTNET-Core.
Now comes the important part of the code, where we will call the API to store the customer record. Refer to the following code block:
$(document).ready(function () {
$('#btnRegister').click(function () {
// Check password and confirm password.
var password = $('#txtPassword').val(),
confirmPassword = $('#txtConfirmPassword').val();
if (password !== confirmPassword) {
alert("Password and Confirm Password don't match!");
return;
}
// Make a customer object.
var customer = {
"gender": $("input[name='gender']:checked").val(),
"firstname": $('#txtFirstName').val(),
"lastname": $('#txtLastName').val(),
"dob": $('#txtDob').val(),
"email": $('#txtEmail').val(),
"telephone": $('#txtMobile').val(),
"fax": $('#txtFax').val(),
"password": $('#txtPassword').val(),
"newsletteropted": false
};
$.ajax({
url: 'http://localhost:57571/api/Customers',
type: "POST",
contentType: "application/json",
data: JSON.stringify(customer),
dataType: "json",
success: function (result) {
alert("A customer record created for: "
+ result.firstname + " " + result.lastname);
},
error: function (err) {
alert(err.responseText);
}
});
});
});
Notice the http://localhost:57571/api/Customers URL and POST HTTP method. This eventually calls the Post method present in the API named PostCustomers. We will definitely have some uniqueness in the table, and in our case, I am taking email as unique for each record. That's why I need to modify the action method a little bit:
// POST: api/Customers
[HttpPost]
public async Task<IActionResult> PostCustomers([FromBody] Customers customers)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
// Unique mail id check.
if (_context.Customers.Any(x => x.Email == customers.Email))
{
ModelState.AddModelError("email", "User with mail id already
exists!");
return BadRequest(ModelState);
}
_context.Customers.Add(customers);
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateException ex)
{
if (CustomersExists(customers.Id))
{
return new StatusCodeResult(StatusCodes.Status409Conflict);
}
else
{
throw;
}
}
return CreatedAtAction("GetCustomers", new { id = customers.Id },
customers);
}
I am returning BadRequest() by adding an error message for the model property email. We will see how this is shown on the browser shortly!
The following image captured from the browser shows you a successful customer creation:
A successful registration of a customer would look something like the preceding image, which shows us the success message in the alert as we have that inside the success method of the ajax call.
You can perform anything you want with the data received from the action method upon completion, as it returns the whole customer object. If you don't believe me, refer to the following screenshot from the source window of the debugger tool:
The response to the POST request with the new Customer created inside the jQuery Ajax success method
So, who did this? Simple, the following return statement, which is inside the POST method, does all the magic:
return CreatedAtAction("GetCustomers", new { id = customers.Id }, customers);
This particular line does a couple of things:
- Sends Status Code: 201 Created as the POST action successfully created the resource.
- Sets a Location header with the actual URL for the resource. If you remember RESTful characteristics, after the POST action, the server should send the URL of the resource. That is what it does.
Let me show you the network tab of developer tools to prove my point. You can also use Postman and analyze it. The following screenshot shows you the response details:
The response received by a POST success request with Status Code and Location Header
Guid is actually the Customer ID as we have defined it in the column type in database, and I am assigning the value to it inside the Customer model class constructor.
Now, if you copy this URL and open it in your browser or Postman, you will get the details of the customer, as the following screenshot shows you:
Let's see a BadRequest() example with a mail ID that already exists. As the taditdash@gmail.com customer already exists, sending another request with the same email ID should send us an error message as a response. Let's have a look:
Remember, we added a line to check the email ID existence and added a ModelState error. That is in action now.
For simplicity of the demo in this book, I am just saving a plain text password. You should not do that in the actual project. Implementing proper encryption for a password is a must.
With this, I would end the registration process. However, there is scope to implement validation at the client side as well as at the server side. You can add attributes to the Model class properties to make it solid so that you don't get bad data from clients. Send a BadRequest() response when ModelState validation fails. Required email-format and password-comparison attributes can be added to the Model class.