Quantcast
Channel: ASP.Net Web API – Bit of Technology
Viewing all articles
Browse latest Browse all 37

Building ASP.Net Web API RESTful Service – Part 5

$
0
0

This is the fifth part of Building ASP.Net Web API RESTful Service Series. The topics we’ll cover are:

Implement HTTP actions POST, PUT, and DELETE In Web API

In this post we’ll continue implementing the other HTTP actions for “CoursesController”, then discuss briefly what we’ll implement in “StudentsController”.

Create new Course using HTTP Post action

We’ll add new method named Post(CourseModel courseModel) to “CoursesController” as the implementation below:


public HttpResponseMessage Post([FromBody] CourseModel courseModel)
{
	try
	{
		var entity = TheModelFactory.Parse(courseModel);

		if (entity == null) Request.CreateErrorResponse(HttpStatusCode.BadRequest, "Could not read subject/tutor from body");

		if (TheRepository.Insert(entity) && TheRepository.SaveAll())
                {
                    return Request.CreateResponse(HttpStatusCode.Created, TheModelFactory.Create(entity));
                }
                else
                {
                    return Request.CreateErrorResponse(HttpStatusCode.BadRequest, "Could not save to the database.");
                }
	}
	catch (Exception ex)
	{

		 return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ex);
	}
}

In the above implementation we’ve to note four things:

  • Method named is “Post”, so the clients needs to issue HTTP Post request.
  • The method accepts parameter of type CourseModel, in Web API parameters with complex types are deserialized from the request body. So the client has to send a serialized representation of a CourseModel object in JSON format.
  • We’ve returned proper “HttpResponseMessange” for all possible scenarios that might happen when we execute this operation. In case the resource is created successfully, server should return HTTP response 201(Resource Created) along with the resource created. It is very important to return the resource created in response message because it will contain CourseId generated at the server.
  • We’ve introduced method named “Parse” in “ModelFactory” class which is responsible to parse the “CourseModel” back to the “Course” domain model object which can be added to our repository. You can use GitHub to browse the latest version of “ModelFactory” and “BaseApiController” classes in order to check the changes introduced to apply “Parse” function.

To test this we need to open fiddler and choose the Composer tab, we’ll issue a POST request to the URI: http://localhost:{your_port}/api/courses/ The request will look as the image below:

FiddlerPostRequest-Courses

In this HTTP POST request we need to note the following:

  • The “content-type” header is set to “application/json” because we are sending JSON data in request body.
  • The “accept” header is set to “application/json” because we are returning response in JSON format.
  • The request body contains deserialized JSON data of the complex “CourseModel”, as we mentioned before, each course has a tutor and related to subject, so sending the Ids for subject and tutor is enough because the “TheModelFactory.Parse” function is responsible to retrieve those objects from database and build valid domain object model which can be used with our repository.

If this POST request executed successfully at the server, and the a new course is created we’ll receive status code 201 (Resource Created) in response header along with the new course created on the server in response body. You can check the image blow:

FiddlerPostResponse-Courses

Update existing Course using HTTP PUT action

We’ll add new method named Put(int Id, CourseModel courseModel) to “CoursesController”, as the implementation below:


	[HttpPatch]
	[HttpPut]
	public HttpResponseMessage Put(int id, [FromBody] CourseModel courseModel)
	{
		try
		{

			var updatedCourse = TheModelFactory.Parse(courseModel);

			if (updatedCourse == null) Request.CreateErrorResponse(HttpStatusCode.BadRequest, "Could not read subject/tutor from body");

			var originalCourse = TheRepository.GetCourse(id);

			if (originalCourse == null || originalCourse.Id != id)
			{
				return Request.CreateResponse(HttpStatusCode.NotModified, "Course is not found");
			}
			else
			{
				updatedCourse.Id = id;
			}

			if (TheRepository.Update(originalCourse, updatedCourse) && TheRepository.SaveAll())
			{
				return Request.CreateResponse(HttpStatusCode.OK, TheModelFactory.Create(updatedCourse));
			}
			else
			{
				return Request.CreateResponse(HttpStatusCode.NotModified);
			}

		}
		catch (Exception ex)
		{
			return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ex);
		}
	}

In the above implementation we’ve to note the below:

  • Method named “PUT”, so the clients needs to issue HTTP PUT request, but we’ve added “HttpPatch” attribute to the Put method, so client can issue PUT or PATCH request and both will be executed using Put method. The difference between Put and Patch that if we want to update all fields of the “CourseModel” we need to use PUT, if we want to update partial fields we need to use PATCH, in our implementation we do not need to distinguish between those two actions.
  • Put method accepts two parameters, the Id of the updated resource which is set in URI, and the updated “CourseModel” which represents complex type deserialized in the request body.
  • We’ve returned proper “HttpResponseMessange” for all possible scenarios that might happen when we execute this operation. In case the resource is updated successfully, server should return HTTP response 200 (OK) along with the resource created. If the resource is not modified the server should return HTTP response 304 (Not modified).

To test this we need to use fiddler and choose the Composer tab, we’ll issue a PUT request to the URI: http://localhost:{your_port}/api/courses/33 The request will look as the image below:

FiddlerPutRequest-Courses

In this HTTP PUT request we need to note the following:

  • The “content-type” header is set to “application/json” because we are sending JSON data in request body.
  • The “accept” header is set to “application/json” because we are returning response in JSON format.
  • The request body contains deserialized JSON data of the updated “CourseModel”.

If this PUT request executed successfully at the server, and the course is updated we’ll receive status code 200 (OK) in response header along with the updated course on the server in response body.

Delete Course using HTTP DELETE action

We’ll add new method named Delete(int Id) to “CoursesController”, as the implementation below:


public HttpResponseMessage Delete(int id)
	{
		try
		{
			var course = TheRepository.GetCourse(id);

			if (course == null)
			{
				return Request.CreateResponse(HttpStatusCode.NotFound);
			}

			if (course.Enrollments.Count > 0)
			{
				return Request.CreateResponse(HttpStatusCode.BadRequest, "Can not delete course, students has enrollments in course.");
			}

			if (TheRepository.DeleteCourse(id) && TheRepository.SaveAll())
			{
				return Request.CreateResponse(HttpStatusCode.OK);
			}
			else
			{
				return Request.CreateResponse(HttpStatusCode.BadRequest);
			}

		}
		catch (Exception ex)
		{
			return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ex.Message);
		}
	}

In the above implementation we’ve to note the below:

  • Method named “DELETE”, so the clients needs to issue HTTP DELETE request.
  • Delete method accepts  the Id parameter of the deleted course, Id is set in URI, and the request body is empty.
  • We’ve returned proper “HttpResponseMessange” for all possible scenarios that might happen when we execute this operation. In case the resource is deleted successfully, server should return HTTP response 200 (OK). If the deletion of the resource failed server should return HTTP response 400 (Bad request) with explanation content why the request failed to process.

To test this we need to use fiddler and choose the Composer tab, we’ll issue a DELETE request to the URI: http://localhost:{your_port}/api/courses/33 Notice that the body of the request is empty, the request will look as the image below:

FiddlerDeleteRequest-Courses

Adding Students Controller to the Project

The new controller “StudentsController” will be responsible to do CRUD operations on Students. The controller will be responsible for executing the actions below:

  • List all available students by sending GET request to URI: http://localhost:{your_port}/api/students/
  • List single student by sending GET request to URI: http://{your_port}/api/students/HasanAhmad Note that we are identifying resource by passing userName not Id here. This method is secured using basic authentication, so resource owner only can query his detailed information once he provide userName and password. We’ll cover this in details once we talk about Securing Web API.
  • Add new student by sending POST request to URI: http://localhost:{your_port}/api/students/
  • Update existing student by sending PUT/PATCH request to URI: http://localhost:{your_port}/api/students/{userName}
  • Delete student by sending DELETE request to URI: http://localhost:{your_port}/api/students/{userName}

I won’t list the code for “StudentsController” here as it is some how identical to “CoursesController”, you can browse it on GitHub. I will just list the new route configuration we’ve added to the “WebApiConfig” class.


	config.Routes.MapHttpRoute(
                name: "Students",
                routeTemplate: "api/students/{userName}",
                defaults: new { controller = "students", userName = RouteParameter.Optional }
            );

So in the next post we’ll cover how to implement Resources Association.

Source code is available on GitHub.



Viewing all articles
Browse latest Browse all 37

Trending Articles