Monday, 31 December 2018

What is HttpResponseException Web API?

When an exception occurs and it is not handled in Web API code then by default exception is converted to 500, internal server error which is not describing anything about the exception. We have to dig down the code where the exception occurred in the code by debugging. But by using HttpResponseException we can handle the exception in the code and could show a friendly message to the end user like 404, page not found, 500 internal server error, 405 Method Not Allowed, 400 Bad Request etc. Below is the example where we are returning error code 404.

public Employee GetEmployees(int id) { Employee emp = repository.Get(id); if (item == null) { throw new HttpResponseException(HttpStatusCode.NotFound); } return emp; }

How ASP.NET Web API routes HTTP requests to controllers?

Create a Web API Project. You will find WebAPIConfig.cs file in App_Start folder. In ASP.NET Web API, a controller is a class that handles HTTP requests. The public methods of the controller are called action methods. When the Web API framework receives a request, it routes the request to an action.
To determine which action to invoke, the framework uses a routing table. The Visual Studio project template for Web API creates a default route. This route is defined in the WebApiConfig.cs file.
When the Web API receives an HTTP request, it tries to match the URI against one of the route templates in the routing table. If no route matches, the client sends a 404 error. Once a matching route is found, Web API selects the controller and the controller action method.
To find the action, Web API looks at the HTTP verb and then looks for an action whose name begins with that HTTP verb name. For example, with a GET request, Web API looks for an action prefixed with "Get", such as "GetEmployee" or "GetAllEmployee". This is only applicable for GET, POST, PUT, DELETE, HEAD, OPTIONS, and PATCH verbs. 

public static class WebApiConfig
    {        public static void Register(HttpConfiguration config)        {            // Web API configuration and services            // Web API routes            config.MapHttpAttributeRoutes();            config.Routes.MapHttpRoute(                name: "DefaultApi",                routeTemplate: "api/{controller}/{id}",                defaults: new { id = RouteParameter.Optional }            );        }    }


How JSONP works to call an ASP.NET Web API service in a cross domain?

JSONP wraps the data in a function. Due to this, we can make a cross-domain call for ASP.Net Web API calls.

JSONP will wrap the data in a function as shown below

CallbackFunction({
    "FirstName" : "Mark",
    "LastName"  : "Hastings",
    "Gender"    : "Male",
})

Below is simple JSON data. Compare this data with JSONP data.


{
    "FirstName" : "Mark",
    "LastName"  : "Hastings",
    "Gender"    : "Male",
}

How to call an ASP.NET Web API service in a cross domain using jQuery ajax?

Browsers does not allow cross domain ajax requests. There are 2 ways to get around this problem

1.     Using JSONP (JSON with Padding) 
2.     Enabling CORS (Cross Origin Resource Sharing)

Using JSONP: Steps to make ASP.NET Web API Service to return JSONP formatted data and consume it from a cross domain ajax request

Step 1 : To support JSONP format, execute the following command using NuGet Package Manager Console which installs WebApiContrib.Formatting.Jsonp package.
Install-Package WebApiContrib.Formatting.Jsonp

Step 2 : Include the following 2 lines of code in Register() method of WebApiConfig class in WebApiConfig.cs file in App_Start folder

var jsonpFormatter = newJsonpMediaTypeFormatter(config.Formatters.JsonFormatter);
config.Formatters.Insert(0, jsonpFormatter);

Step 3 : In the ClientApplication, set the dataType option of the jQuery ajax function to jsonp 

dataType: 'jsonp'

<!DOCTYPE html>
<html>
<head>
    <title></title>
    <meta charset="utf-8" />
    <script src="Scripts/jquery-1.10.2.js"></script>
    
    <script type="text/javascript">
        $(document).ready(function () {
            var ulEmployees = $('#ulEmployees');
            $('#btn').click(function () {
                $.ajax({
                    type: 'GET',
                    url: "api/employees/",
                    dataType: 'jsonp',
                    success: function (data) {
                        ulEmployees.empty();
                        $.each(data, function (index, val) {
                            var fullName = val.FirstName + ' ' + val.LastName;
                            ulEmployees.append('<li>' + fullName + '</li>');
                        });
                    }
                });
            });
            $('#btnClear').click(function () {
                ulEmployees.empty();
            });
        });
    </script>

</head>
<body>
    <div>
        <input id="btn" type="button" value="Get All Employees" />
        <input id="btnClear" type="button" value="Clear" />
        <ul id="ulEmployees" />
    </div>
</body>
</html>

Enabling CORS: To allow cross domain ajax calls by enabling CORS

Step 1 : 
Install Microsoft.AspNet.WebApi.Cors package. Execute the following command using NuGet Package Manager Console. Make sure to select "EmployeeService" project from "Default project" dropdown.

Install-Package Microsoft.AspNet.WebApi.Cors 

Step 2 : Include the following 2 lines of code in Register() method of WebApiConfig class in WebApiConfig.cs file in App_Start folder

EnableCorsAttribute cors = new EnableCorsAttribute("*", "*", "*");
config.EnableCors();

Step 3 : In the ClientApplication, set the dataType option of the jQuery ajax function to json

dataType: 'json'

<!DOCTYPE html>
<html>
<head>
    <title></title>
    <meta charset="utf-8" />
    <script src="Scripts/jquery-1.10.2.js"></script>
    
    <script type="text/javascript">
        $(document).ready(function () {
            var ulEmployees = $('#ulEmployees');
            $('#btn').click(function () {
                $.ajax({
                    type: 'GET',
                    url: "api/employees/",
                    dataType: 'json',
                    success: function (data) {
                        ulEmployees.empty();
                        $.each(data, function (index, val) {
                            var fullName = val.FirstName + ' ' + val.LastName;
                            ulEmployees.append('<li>' + fullName + '</li>');
                        });
                    }
                });
            });
            $('#btnClear').click(function () {
                ulEmployees.empty();
            });
        });
    </script>

</head>
<body>
    <div>
        <input id="btn" type="button" value="Get All Employees" />
        <input id="btnClear" type="button" value="Clear" />
        <ul id="ulEmployees" />
    </div>
</body>
</html>

EnableCors attribute can be applied on a specific controller or controller method. 

If applied at a controller level then it is applicable for all methods in the controller. To apply it at the controller level

1. There is no need to create an instance of 
EnableCorsAttribute in Register() method of WebApiConfig.cs file. Call the EnableCors() method without any parameter values.

config.EnableCors();


2. Apply the  EnableCorsAttribute on the controller class
[EnableCorsAttribute("*", "*", "*")]
public class EmployeesController : ApiController
{
}


In the same manner, you can also apply it at a method level if you wish to do so.


To disable CORS for a specific action apply [
DisableCors] on that specific action

When CORS is enabled, the browser sets the origin header of the request to the domain of the site making the request. The server sets Access-Control-Allow-Originheader in the response to either * or the origin that made the request. * indicates any site is allowed to make the request.