Prerequisite
- Basic C# coding knowledge
- Minimum knowledge of Web API
- Understanding the REST service
- Basic understanding of Fiddler
What are Web API Action Results?
Before we get into our topic, types of Web API Action results, let’s discuss Web API service methods and REST service response.(If you are aware of action method concept in Web API, you can directly start from Types of Web API Action results section). Let’s assume, we are writing a Web API service method to return the user details based on the User ID parameter. As a beginner, we create a method with UserID as the parameter and the return type would be UserProfile entity type as shown in the following code (I have added the User profile model and UserProfileDB classes on the same location, but as per the standards, we have to create them in a separate folder structure).
The Code
public class UserProfileController : ApiController
{
[HttpGet]
[Route("UserProfile/GetUserProfile/{UserId}")]
public UserProfile GetUserProfile(int UserId)
{
return new UserProfileDB().GetUserProfile(UserId);
}
}
public class UserProfile
{
public int UserId { get; set; }
public string UserName { get; set; }
public string Location { get; set; }
public int PIN { get; set; }
public int Age { get; set; }
public string Sex { get; set; }
public string Occupation { get; set; }
public float AnnualIncome { get; set; }
public string MaritalStatus { get; set; }
public string Nationality { get; set; }
}
public class UserProfileDB
{
public UserProfile GetUserProfile(int UserId)
{
//write the code logic to retrieve user data from database
return new UserProfile();
}
}
In the above code, the return type is UserProfile where we call here Web API Action Result. When the client calls this service by passing the UserID, the client will get the user details in JSON/XML format depending on the configuration.
Minimum things to know about the response
When we are working with Web API, we should be aware of the returned result. As Web API service is a REST enabled service, we should beware of / take care of the following things at least.
Highlight the above 3 by taking Fiddler Raw response as an example for the UserProfile in the following figure. (I have called the GetUserProfile service from Fiddler and the response is as follows).
Types of Web API Action Results
Let’s see how we are going to handle returned types in Web API. Web API provides a facility to return any of the following kinds of Action Results.
- Void
- Any Entity/Datatype
- HttpResponseMessage
- IHttpActionResult
Void
Void means it doesn’t return anything. So, let’s see how it works on Web API action method.
Following action method returns void.
[HttpGet]
public void LogMessageinDB(string Message)
{
new UserProfileDB().LogMessageinDB(Message);
}
I am calling this service method using Fiddler's composer option.
And, see the response of the service.
We won’t get the data from the service and the status will always be 204 - no content.
When we have to use Void action results
When there is a requirement where the next process is not dependent on the action result, like any kind of loggings.
Any Entity/Datatype
Web API action method can contain any entity type as return type. As mentioned in the first example of What is Web API Action Results, we can use any entity type as the return type. But the problem here is that we get 200 (OK) status code every time on a successful response.
[HttpGet]
[Route("UserProfile/GetUserProfile/{UserId}")]
public UserProfile GetUserProfile(int UserId)
{
return new UserProfileDB().GetUserProfile(UserId);
}
Following is the result of the above service call in Fiddler.
Result in the Fiddler
When you observe the above picture, the status code is 200 and the result is in JSON format at the bottom.
When we have to use this kind of action result
It is not recommended to use because of two reasons -
- We cannot explain/convey the client with the various status codes as we get 200 (OK) status code every time.
- There is no guarantee that the above service will return the required result at every time. There could be an issue with the data or the DB Server or anything can happen. In these situations, the consumer won’t get the data and will get an error in response, i.e., the status code 500 always. Moreover, the client receives complete stack trace error message.
To overcome these problems, Web API provided Action results, like HttpResponseMessage and IHttpActionResult.
HttpResponseMessage
To customize the action result, we can use HttpResponseMessage as return type (action result) of an action method.
We can customize the response by providing status code, content type, and data to be returned to HttpResponseMessage.
Go through the following example.
[HttpGet]
[Route("UserProfile/GetUserLoginID/{UserId}")]
public HttpResponseMessage GetUserLoginId(int UserId)
{
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Accepted,"Ravikiran");
response.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("text/plain");
return response;
}
When we call the above action method, we get the result as following (shown in the Fiddler).
Result of the above call will be as follows -
We can observe that the default return type is modified to text/plain and the status code is 202 (Accepted).
We can return the complex type data using HttpResponseMessage.
IHttpActionResult
IHttpActionResult has been introduced in Web API 2. This is a little-advanced concept of HttpResponseMessage. IHttpActionResult ultimately returns HttpResponseMessage by providing the customization and reusability features to the developer.
IHttpActionResult contains ExecuteAsync method to create an instance of HttpResponseMessage asynchronously. We have to add some code logic in the implemented class as per our requirement. When user/client calls the action method of IHttpActionResult type, Web API automatically hits the ExecuteAsync method.
Steps to implement IHttpActionResult
Initially, we have to create the return type by inheriting IHttpActionResult. Please see the following code snippet.
public class UserProfileReturnType : IHttpActionResult
{
UserProfile userProfile;
HttpRequestMessage httpRequestMessage;
HttpResponseMessage httpResponseMessage;
public UserProfileReturnType(UserProfile data, HttpRequestMessage request)
{
userProfile = data;
httpRequestMessage = request;
}
public System.Threading.Tasks.Task<HttpResponseMessage> ExecuteAsync(System.Threading.CancellationToken cancellationToken)
{
httpResponseMessage =httpRequestMessage.CreateResponse(HttpStatusCode.Found, userProfile);
return System.Threading.Tasks.Task.FromResult(httpResponseMessage);
}
}
In the above code, we have created UserProfileReturnType and given the definition for ExecuteAsync Method by adding some custom logic.
Now, we can use UserProfileReturnType as return type whenever we want to return the UserProfile.
[HttpGet]
[Route("UserProfile/GetUserProfileIHAR/{UserId}")]
public IHttpActionResult GetUserProfileIHAR(int UserId)
{
//get the user profileof UserID
UserProfile userProfile = new UserProfileDB().GetUserProfile(UserId);
//return UserProfileReturnType HttpResponseMessage
return new UserProfileReturnType(userProfile, Request);
}
I am going to call GetUserProfileIHAR service method by passing UserId using Fiddler.
The result will be as follows.