HttpResponseMessage and IHttpActionResult

by Sachin Singh


Posted on Monday, 21 December 2020

Tags: HttpResponseMessage vs 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 was first introduced introduced in Web API 2 that works as a return type for Action methods , this means Instead of returning HttpResponseMessage from a controller action, we can now return IHttpActionResult.Using the IHttpActionResult interface over HttpResponseMessage have many adavantages, some of them are
    1. The code becomes cleaner and easier to read, which leads to better maintainability.
    2. Unit testing controller action methods also becomes much simpler.

Consider the above EmployeeController. Notice both the Get() methods return HttpResponseMessage. To create the HttpResponseMessage, we often use CreateResponse() method of the Request objectand send the necessary data or we use CreateErrorResponse() method of the Request object to send an error response. these makes the code lengthy and could be replaced by IHttpActionResult.

Let's rewrite the above example with the help of IhttpActionResult and the helper methods, for this replace all instances of HttpResponseMessage with IhttpActionResult and to create Response, use Ok() helper method which accepts the object we want to return and create HttpResponseMessage internally it also set the status code to 200 Ok automatically.

Also notice, with IHttpActionResult the code becomes 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);
        }
    }

Web API provides us several helper methods other than Ok() or NotFound(),as listed below. All these methods are used to return different types of HttpResponseMessages and all of them implements IHttpActionResult.

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