Posted on 12/21/2020 12:36:05 PM by Admin

HttpResponseMessage and IHttpActionResult

In order to understand the difference and similarities between HttpResponseMessage and IHttpActionResult , you first need to understand why does these return types even exist, In .Net to return an integer you have int dataType, to return float or double or decimal, you have all these primitive dataType , if you want to return collection of object then you have IEnummerable, List , Array and a lot of things, then why the heck do you need one more return type?

Since we can return primitive types or complex types to the user, why HttpResponseMessage?

Let's consider a scenario where we want to return all Employees or an Employee by his Id. we can simply create methods like shown below.



public class EmployeeController : ApiController
    {
        public IEnumerable Get()
        {
            return FetchFromDB();
        }

        public Employee Get(int id)
        {
            return FetchFromDB().Where(x=>x.Id==id).SingleOrDefault();
        }
        public List FetchFromDB()
        {
            List emps = new List()
            {
                new Employee(){Id=1,Name="Sachin",Salary=350000},
                new Employee(){Id=2,Name="Michael",Salary=80000},
                new Employee(){Id=3,Name="Geetha",Salary=200000},
                new Employee(){Id=4,Name="Arjun",Salary=45000},
                new Employee(){Id=5,Name="Varun",Salary=67000},
            };
            return emps;
        }
    }

And when, we run the application and issue get request from browser , we get below results.

Get Request
Get Request
GetbyId
Get Request by Id

You can see, we are getting the desired output, then what's the problem , why don't we use IEnumberable or Employee (Complex type) directly ,to return data in web API?

This is because, we use web API to create Rest services, and Rest services means respecting the Http, And respecting the Http means return everything a Http needs to carry message appropriately.

Let's see what are we missing.

case 1.what if List of employee gets null.(we must return http status code 204 (No content) with no employee found message)

case 2.what if any run time error occurs.(we must return 500 internal server error).

case 3.what if there is no employee of specified Id exist.( we must return 204 status code, with no employee with specified Id exist message. )

In short ,No we are not following rest principles completely. Rest means respect the http protocol and utilize it as much as you can.

To check what is the problem , issue a get request for employee who doesn't exist like employee with id=90 ,with fiddler or postman and check the response header.

GetbyId2
Response Header

As you can see, even if there is no employee with such Id and we are getting null response but Response header contains Http Status Code 200 Ok, which is manipulating.

Lets modify the above code to get the desired outcome and fulfill the rest principles completely.


   public List FetchFromDB()
        {
            List emps = new List()
            {
                new Employee(){Id=1,Name="Sachin",Salary=350000},
                new Employee(){Id=2,Name="Michael",Salary=80000},
                new Employee(){Id=3,Name="Geetha",Salary=200000},
                new Employee(){Id=4,Name="Arjun",Salary=45000},
                new Employee(){Id=5,Name="Varun",Salary=67000},
            };
            return emps;
        }

        public HttpResponseMessage GetAllEmployee()
        {
            try
            {
               
                    var Employees = FetchFromDB();
                    if (Employees != null)
                    {
                        return Request.CreateResponse(HttpStatusCode.OK, Employees);
                    }
                    return Request.CreateErrorResponse(HttpStatusCode.NotFound, "No result found");
               
            }
            catch
            {
                return new HttpResponseMessage(HttpStatusCode.InternalServerError);
            }

        }

        public HttpResponseMessage GetEmployeeById(int Id)
        {
            try
            {


                Employee emp = FetchFromDB().Where(x => x.Id == Id).SingleOrDefault();
                    if (emp != null)
                    {
                        return Request.CreateResponse(HttpStatusCode.OK, emp);
                    }
                    return Request.CreateErrorResponse(HttpStatusCode.NotFound, "Employee with id " + Id + "Not found");

                
            }
            catch
            {
                return new HttpResponseMessage(HttpStatusCode.InternalServerError);
            }
        }

Now ,Run the application and request employee who doesn't exist like employee with id 90. you will get below representation.

Create Empty Web API project
No Result found Error representation

Now, everything is great, we are respecting the Http protocol completely.

I think now you got the point , why does HttpResponseMessage exist? yes , it is used to return data along with the Http Status code and additional error Messages.

Now Let's come to IHttpActionResult , the purpose of IHttpActionResult is exactly the same , it also serves the same purpose of returning data with http status code and additional error messages if there is any.

Now, you might be thinking then why did Microsoft introduce a new return type in the form of IHttpActionResult when we already had HttpResponseMessage to serve the same purpose?

IHttpActionResult is introduced in Web API 2 that can be returned from a controller action method. Instead of returning HttpResponseMessage from a controller action, we can now return IHttpActionResult. There are 2 main advantages of using the IHttpActionResult interface.
    1. The code is cleaner and easier to read
    2. Unit testing controller action methods is much simpler.

Consider the above EmployeeController. Notice both the Get() methods return HttpResponseMessage. To create the HttpResponseMessage, we either use CreateResponse() or CreateErrorResponse() methods of the Request object.

In the following example, we have replaced both instances of HttpResponseMessage with IHttpActionResult. To return status code 200, we used Ok() helper method and to return status code 404, we used NotFound() method. To the Ok() method we have passed the type we want to return from the action method.

Also notice, the code is now much cleaner and simpler to read.

   public class EmployeeController : ApiController
    {     
        public List FetchFromDB()
        {
            List emps = new List()
            {
                new Employee(){Id=1,Name="Sachin",Salary=350000},
                new Employee(){Id=2,Name="Michael",Salary=80000},
                new Employee(){Id=3,Name="Geetha",Salary=200000},
                new Employee(){Id=4,Name="Arjun",Salary=45000},
                new Employee(){Id=5,Name="Varun",Salary=67000},
            };
            return emps;
        }

        public IHttpActionResult Get()
        {
            return Ok(FetchFromDB());
        }

        public IHttpActionResult Get(int id)
        {
            var employee = FetchFromDB().FirstOrDefault(e => e.Id == id);
            if (employee == null)
            {
                //return NotFound();
                return Content(HttpStatusCode.NotFound, "employee not found");
            }

            return Ok(employee);
        }
    }

In addition to Ok() and NotFound() helper methods, we have the following methods that we can use depending on what we want to return from our controller action method. All these methods return a type, that implements IHttpActionResult interface.

• BadRequest()
• Conflict()
• Created()
• InternalServerError()
• Redirect()
• Unauthorized()