Calling an ASP.NET Web API from jQuery
I’ve been playing with ASP.NET Core Web API recently … here’s a quick post on calling one of these APIs using jQuery Ajax …
Creating the API
The API is going to allow clients to:
- get a list of people
- get a single person
- create a new person
Here’s the very simple person model:
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
}
For simplicity, I’m going to use a hardcoded list of people and not going to persist the people in a database. Here’s the API controller constructor and the hardcoded list:
private List<Person> People;
public PersonController()
{
People = new List()
{
new Person() {Id=1, Name = "Fred Blogs", Email="fred.blogs@someemail.com" },
new Person() {Id=2, Name = "James Smith", Email="james.smith@someemail.com" },
new Person() {Id=3, Name = "Jerry Jones", Email="jerry.jones@someemail.com" }
};
}
The action method in PersonController
to get the list of all the people is very simple:
// GET: api/person
[HttpGet]
public IActionResult Get()
{
return new ObjectResult(People);
}
The action method in PersonController
to get a single person is below. The person id will be passed in from the URL path. We return the “Not Found” HTTP status code if the id isn’t in our hardcoded list and the JSON represenation of the found person if it does exists.
// GET api/person/id
[HttpGet("{id}",Name ="GetPerson")]
public IActionResult Get(int id)
{
Person person = (from p in People where p.Id == id select p).FirstOrDefault();
if (person == null)
{
return NotFound();
}
else
{
return new ObjectResult(person);
}
}
The action method in PersonController
to create a person is below. The person object is passed in from the HTTP body that has been posted. If the body is missing we return a “Bad Request” HTTP status code. If we do have a person object from the HTTP body then the person id is generated, the person is added to the hardcoded list and we return a “Created” HTTP status code with the person in the response body containing the generated person id.
As well as dealing with returning the HTTP status code and the response body, the call to CreatedAtRoute()
, also sets the Location
HTTP header to the URL that the client could use to request the person just created. This is the reason for the Get
action method having the GetPerson
name parameter in the attribute and being referenced as the first parameter in CreatedAtRoute()
.
// POST api/person
[HttpPost]
public IActionResult Post([FromBody]Person person)
{
if (person == null)
{
return BadRequest();
}
int nextId = (from p in People select p.Id).Max() + 1;
person.Id = nextId;
People.Add(person);
return CreatedAtRoute("GetPerson", new { id = nextId }, person);
}
Creating the frontend page
Below is the HTML markup (referencing bootstrap CSS classes) that allows the user get a list of people:
<div class="container">
<div class="row">
<div class="col-sm-6">
<h2>Get all people</h2>
<div>
<button class="btn btn-default" id="getPeople">Get People</button>
</div>
<div>
<input type="text" class="form-control" id="getPeopleResult" />
</div>
</div>
</div>
</div>
Below is JavaScript for the getPeople
button click handler. We use $.ajax()
to call our person API. It is important to set contentType
to application/json
or our API won’t be reached. We put the names of the people returned in a pipe delimited list into the getPeopleResult
textbox if the API call is successful.
<script>
$('#getPeople').click(function (e) {
$("#getPeopleResult").val("");
$.ajax({
contentType: 'application/json',
type: "GET",
url: "api/person",
success: function (data, textStatus, jqXHR) {
data.forEach(function (person) {
$("#getPeopleResult").val($("#getPeopleResult").val() + person.name + "|");
});
},
error: function (jqXHR, textStatus, errorThrown) {
$("#getPeopleResult").val(jqXHR.statusText);
}
});
});
</script>
Below is the HTML markup (referencing bootstrap CSS classes) that allows the user to get a single person:
<div class="container">
<div class="row">
<div class="col-sm-6">
<h2>Get a Person</h2>
<div class="form-group">
<label for="id">Id</label>
<input type="text" class="form-control" id="id" />
</div>
<div>
<button class="btn btn-default" id="getPerson">Get</button>
</div>
<div>
<input type="text" class="form-control" id="getPersonResult" />
</div>
</div>
</div>
</div>
Below is JavaScript for the getPerson
button click handler. The code is very simular to the getPeople
button click handler except it calls the API to get a single person and outputs the single person’s name in the getPersonResult
textbox.
$("#getPerson").click(function(e) {
$("#getPersonResult").val("");
$.ajax({
contentType: "application/json",
type: "GET",
url: "api/person/" + $("#id").val(),
success: function(data, textStatus, jqXHR) {
$("#getPersonResult").val(data.name);
},
error: function(jqXHR, textStatus, errorThrown) {
$("#getPersonResult").val(jqXHR.statusText);
}
});
});
Below is the HTML markup that allows the user to create a person:
<div class="container">
<div class="row">
<div class="col-sm-6">
<h2>Create a new Person</h2>
<div class="form-group">
<label for="name">Name</label>
<input type="text" class="form-control" id="name" />
</div>
<div class="form-group">
<label for="emailAddress">Email</label>
<input type="email" class="form-control" id="emailAddress" />
</div>
<div>
<button class="btn btn-default" id="create">Create</button>
</div>
<div>
<input type="text" class="form-control" id="postResult" />
</div>
</div>
</div>
</div>
Below is JavaScript for the create
button click handler. Again we use $.ajax()
to call our person API but this time we POST
to it. We create an object literal containing the name and email of the person and use JSON.stringify()
so this can be passed into the data
option in $.ajax()
. We set whether the operation has been successful in the postResult
textbox along with the generated person id. It is worth noting that the data
in the success
callback is the original data and not the data in the response. The response body can be obtained from jqXHR.responseText
.
$("#create").click(function(e) {
$.ajax({
contentType: "application/json",
type: "POST",
url: "api/person",
data: JSON.stringify({
name: document.getElementById("name").value,
email: document.getElementById("emailAddress").value
}),
success: function(data, textStatus, jqXHR) {
$("#postResult").val("Person created ok. Id=" + jqXHR.responseText);
},
error: function(jqXHR, textStatus, errorThrown) {
$("#postResult").val(jqXHR.statusText);
}
});
});
If you to learn about using React with ASP.NET Core you might find my book useful: