DotNetStories
This is the second post discussing the
ASP.Net Web API. I will continue building a small
ASP.Net MVC 4.0 application that I started
implementing in my last post.
You can have a look at the first post here. In this hands-on example I will show you how to create new footballer items,update a new footballer item,delete a new footballer item.
I will also refactor the implementation for the
GET operations-methods from my last post.I will
present you with a full CRUD hands-on example. This
will be based in the RESTful WEB API paradigm and its
four main HTTP methods. GET will retrieve the
footballer items from the specified URI.PUT updates a
resource (footballer item) at a specified URI.POST
will create a new resource (footballer item).DELETE
will delete a resource (footballer item) at a specified
URI.
Let's move on to actually building the application.
1) Launch Visual Studio , I have named my application "WebApi", and open the application.
2) As I said earlier I will refactor the code I created in the first post.
Inside the Models folder my class file
Footballer.cs looks exactly the same.
public class Footballer
{
public int FootballerID { get; set; }
public
string FirstName { get; set; }
public string
LastName { get; set; }
public double Weight {
get; set; }
public double Height { get; set;
}
public DateTime JoinedClub { get; set; }
public string PositionPlayed { get; set; }
public int GoalsScored { get; set; }
}
I need to create a collection of objects - footballer
objects.I will use the Repository Pattern to separate
the collection of objects from our service
implementation.
In Solution Explorer, right-click the Models folder. Select Add, then select New Item. From the available Templates pane, select Installed Templates. Under C#, select Code. In the list of code templates, select Interface. Name the interface IFooballerRepository.cs.
The code for the interface implementation follows
public interface IFootballerRepository
{
IEnumerable<Footballer> GetPlayers();
Footballer GetFooballerById(int id);
Footballer AddFootballer(Footballer item);
void RemoveFootballer(int id);
bool
UpdateFootballer(Footballer item);
}
3) Now, we obviously need to implement this interface. We
need to add another class to the Models folder, named
FootballerRepository.cs. This class will implement
the IFootballerRepository interface. Add the
following implementation:
public class FootballerRepository
:IFootballerRepository
{
private List<Footballer> footballers = new
List<Footballer>();
private int
_nextId = 1;
public
FootballerRepository()
{
footballers.Add(new Footballer {
FootballerID = 1, FirstName = "Steven", LastName =
"Gerrard", Height = 1.85, Weight = 85, JoinedClub =
DateTime.Parse("12/12/1999"), PositionPlayed = "Attacking
Midfielder", GoalsScored = 23 });
footballers.Add(new Footballer { FootballerID = 2,
FirstName = "Jamie", LastName = "Garragher", Height =
1.89, Weight = 89, JoinedClub =
DateTime.Parse("12/02/2000"), PositionPlayed = "Central
Defender", GoalsScored = 2 });
footballers.Add(new Footballer { FootballerID = 3,
FirstName = "Luis", LastName = "Suarez", Height = 1.72,
Weight = 73, JoinedClub = DateTime.Parse("12/01/2012"),
PositionPlayed = "Striker", GoalsScored = 27 });
}
public
IEnumerable<Footballer> GetPlayers()
{
return footballers;
}
public Footballer GetFooballerById(int id)
{
return footballers.Find(f =>
f.FootballerID == id);
}
public Footballer
AddFootballer(Footballer item)
{
if (item == null)
{
throw new ArgumentNullException("item");
}
item.FootballerID = _nextId++;
footballers.Add(item);
return item;
}
public void RemoveFootballer(int
id)
{
footballers.RemoveAll(f => f.FootballerID == id);
}
public bool UpdateFootballer(Footballer item)
{
if (item == null)
{
throw new ArgumentNullException("item");
}
int index = footballers.FindIndex(f
=> f.FootballerID == item.FootballerID);
if (index == -1)
{
return false;
}
footballers.RemoveAt(index);
footballers.Add(item);
return true;
}
}
Let me explain the implementation above.
I create a generic collection of Fooballer objects
(footballers)
private List<Footballer> footballers = new
List<Footballer>();
Then I populate the list with objects that live in the computer's memory
public FootballerRepository()
{
footballers.Add(new Footballer {
FootballerID = 1, FirstName = "Steven", LastName =
"Gerrard", Height = 1.85, Weight = 85, JoinedClub =
DateTime.Parse("12/12/1999"), PositionPlayed = "Attacking
Midfielder", GoalsScored = 23 });
footballers.Add(new Footballer { FootballerID = 2,
FirstName = "Jamie", LastName = "Garragher", Height =
1.89, Weight = 89, JoinedClub =
DateTime.Parse("12/02/2000"), PositionPlayed = "Central
Defender", GoalsScored = 2 });
footballers.Add(new Footballer { FootballerID = 3,
FirstName = "Luis", LastName = "Suarez", Height = 1.72,
Weight = 73, JoinedClub = DateTime.Parse("12/01/2012"),
PositionPlayed = "Striker", GoalsScored = 27 });
}
Well, I trust you have some knowledge of C# and collection initializers which is a C# 3.0 feature. Have a look here if you want to learn more about it.The individual object initializers are enclosed in braces and separated by commas.
Next, I implement two simple methods. GetPlayers() returns a list of players.GetFooballerById(int id) returns a single footballer by its ID.
public IEnumerable<Footballer> GetPlayers()
{
return footballers;
}
public Footballer GetFooballerById(int id)
{
return footballers.Find(f =>
f.FootballerID == id);
}
Next I am implementing the
AddFootballer method which is pretty straightforward
method. If there is no item-object we throw an exception. If
there is an item we give it a new ID and add the object to
the collection.
public Footballer AddFootballer(Footballer item)
{
if (item == null)
{
throw new ArgumentNullException("item");
}
item.FootballerID = _nextId++;
footballers.Add(item);
return item;
}
Next I am implementing the RemoveFootballer method.I
just remove an object from the collection with a specific
id.
public void RemoveFootballer(int id)
{
footballers.RemoveAll(f =>
f.FootballerID == id);
}
Finally I implement the UpdateFootballer method.If
there is no item-object we throw an exception. Then I find
the index of the object in the collection array according to
its ID and then remove it and add the new one.
public bool UpdateFootballer(Footballer item)
{
if (item == null)
{
throw new ArgumentNullException("item");
}
int index = footballers.FindIndex(f
=> f.FootballerID == item.FootballerID);
if (index == -1)
{
return false;
}
footballers.RemoveAt(index);
footballers.Add(item);
return true;
}
4) Now we need to change the code we have written for our controller FootballerController.cs in the Controllers folder.
Comment everything inside this class and just leave the code
below
public class FootballerController : ApiController
{
}
The complete implementation follows
public class FootballerController : ApiController
{
static readonly IFootballerRepository
repository = new FootballerRepository();
public IEnumerable<Footballer> GetPlayers()
{
return repository.GetPlayers();
}
public Footballer
GetFooballerById(int id)
{
var footballer = repository.GetFooballerById(id);
if (footballer == null)
{
throw new
HttpResponseException(HttpStatusCode.NotFound);
}
return footballer;
}
public HttpResponseMessage
PostFootballer(Footballer footballer)
{
footballer = repository.AddFootballer(footballer);
var response =
Request.CreateResponse<Footballer>(HttpStatusCode.Created,
footballer);
string uri =
Url.Link("DefaultApi", new { id = footballer.FootballerID
});
response.Headers.Location = new
Uri(uri);
return response;
}
public void PutFootballer(int id,
Footballer footballer)
{
footballer.FootballerID = id;
if
(!repository.UpdateFootballer(footballer))
{
throw new
HttpResponseException(HttpStatusCode.NotFound);
}
}
public void
DeleteFootballer(int id)
{
Footballer footballer =
repository.GetFooballerById(id);
if
(footballer == null)
{
throw new
HttpResponseException(HttpStatusCode.NotFound);
}
repository.RemoveFootballer(id);
}
}
In ASP.NET Web API, a controller is a class that handles HTTP requests from the client.Now I will explain what I have implemented in this class and what methods have been created.
I am adding a field that holds an
IFootballerRepository instance.
static readonly IFootballerRepository repository = new FootballerRepository();
This is the method to get a list of
footballers.Well, nothing really to explain here.
public IEnumerable<Footballer>
GetPlayers()
{
return
repository.GetPlayers();
}
This is the method to get a footballer item by id.This
method name also starts with Get.This method has a
parameter named id. This parameter is mapped to the
id segment of the URI path.
The method will throw an exception of type HttpResponseException if id is not valid. This exception will be translated by Web API as a 404 (Not Found) error.
public Footballer GetFooballerById(int id)
{
var footballer =
repository.GetFooballerById(id);
if
(footballer == null)
{
throw new
HttpResponseException(HttpStatusCode.NotFound);
}
return footballer;
}
Now I would like to explain again how the ASP.NET Web API knows how to map URIs to
our controller methods.
The ASP.NET Web API framework for
each HTTP message decides which controller receives the
request by consulting a route table. The Web API project
contains a default route that you can find in the WebApiConfig.cs file.
/api/{controller}/{id}
The {controller} and {id} are just
placeholders.
{controller} is matched to the controller name. {controller} in my case
is footballer.
The HTTP request method is matched to the method name.
(This rule applies only to GET, POST, PUT, and DELETE
requests.)
/api/footballer will match
the GetPlayers() method
/api/footballer/1 will match
the GetFooballerById(1) method
Next I am implementing the PostFootballer method.This
will create a new footballer item.The new item is created
when the client sends a HTTP POST request to the
server with the new footballer object in body of the request
message.
public HttpResponseMessage PostFootballer(Footballer
footballer)
{
footballer =
repository.AddFootballer(footballer);
var
response =
Request.CreateResponse<Footballer>(HttpStatusCode.Created,
footballer);
string uri =
Url.Link("DefaultApi", new { id = footballer.FootballerID
});
response.Headers.Location = new
Uri(uri);
return response;
}
The way POST requests are getting handled, we define a method whose name starts with Post. The method takes a parameter of type Footballer. The clients to sends to the server a serialized representation of a footballer object, using either XML or JSON for the serialization.
Next we must think of the response code.The Web API framework sets the response status code to 200 (OK). HTTP/1.1 protocol dictated that when a POST request results in the creation of a resource, the server should reply with status 201 - Created.When the server creates a resource, it should include the URI of the new resource in the Location header of the response.
Next I am implementing the PutFootballer method.This method will update a footballer item.This method name starts with Put which makes the Web API to match it to PUT requests. The method takes two parameters, the footballer Id and the updated footballer object. The id parameter is taken from the URI path, and the footballer parameter is deserialized from the request body. The ASP.NET Web API framework takes simple parameter types from the route. Complex types are taken from the request body.
public void PutFootballer(int id, Footballer
footballer)
{
footballer.FootballerID = id;
if
(!repository.UpdateFootballer(footballer))
{
throw new
HttpResponseException(HttpStatusCode.NotFound);
}
}
Next I am implementing the DeleteFootballer method.We define a method whose name starts with Delete so the Web API matches it to DELETE requests.
Τhe method has a parameter named id. This parameter
is mapped to the "id" segment of the URI path. Ιf the
footballer object is not found an exception is thrown. If
the deletion is successful then status code 204 (No Content)
will be returned.
public void DeleteFootballer(int id)
{
Footballer footballer =
repository.GetFooballerById(id);
if
(footballer == null)
{
throw new
HttpResponseException(HttpStatusCode.NotFound);
}
repository.RemoveFootballer(id);
}
In the next and final post in this series I will build the Index.cshtml using Knockout which is a JavaScript library that helps developers to create rich, responsive displays when a clean underlying data model exists.
I think that this is enough material for one post and before
I implement Index.cshtml I must introduce
Knockout library to you.
Hope it helps!!!
Comments have been disabled for this content.