Chapter 4. Communicating with the Server Using AngularJS

This chapter mainly focuses on how AngularJS communicates with server-side code, such as web APIs, web services, or Data Access Layer (DAL). In this chapter, we will discuss how to retrieve data from the server using $http and $resources. This chapter also talks about the authentication and security of an AngularJS application.

This chapter is organized as follows:

  • Communicating with the server using $http:
    • GET
    • POST
    • HEAD
    • DELETE
    • PUT
    • JSONP
    • PATCH
  • Communicating with RESTful services
  • Authentication
  • Securing applications

Communicating with the server using $http

A web application is the communication between a client and server made using the HTTP protocol where the server is responsible for serving web pages. The client, which is a web browser, requests a web page from the server, receives the server's response, and displays the response to the user. The user uses the client (web browser) to display web pages, watch videos online, and so on. Client-side programming and server-side programming refers to the programming that runs on a specific side of the server or client.

The following are the steps involved in client-server communication:

  1. The user opens the browser (the client) on a computer.
  2. User enters the URL to browse a specific web page, such as http://www.google.com.
  3. The client sends the request to the server and waits for the server's response.
  4. The client receives the server's response and renders the page into human-readable form.

There are two different types of renderings: server side and client side. In server-side rendering, the client (browser) fetches web pages from a server over HTTP. In client-side rendering, JavaScript running on the client (browser) produces or manipulates the DOM. All browsers understand JavaScript and because of this, client-side rendering can be accomplished using JavaScript without sending a request to the server and waiting for its response. The advantage of client-side rendering is that the user can update a web page instantly. When the user clicks on any button, the click event updates the information on the page rather than waiting for a few hundred milliseconds to get a response from the server in order to display the page on the client side.

Best practice to render web applications is to render the initial state of the web page on the server and interactive widgets and then to re-render the part of the web page that needs to be updated on the client side. It is typical to render the meat of the page on the server side and then to enhance the page on the client side with a client library using jQuery or the AngularJS framework.

Server-side programming and client-side programming cannot be combined together because typically, server-side and client-side programming are performed in different programming languages. Server-side programming is the program that generally runs on the server and interacts with the resource management tools, such as SQL, Oracle databases, and so on. For server-side programming, we can use any server-side programming language, such as C#, Visual Basic .Net, C++, Java, and so on.

Client-side programming can be achieved using a client programming library or framework, such as jQuery, AngularJS Backbone, and so on. All client-side libraries and frameworks are based on JavaScript. The client-side program runs on the client. The following figure shows the communication between different clients and the server:

Communicating with the server using $http

The preceding figure shows how different clients (browsers) send requests to a web server and receive a response using the HTTP protocol.

Retrieving data with $http using GET

These days, fetching data from a server is different from when Active Server Pages (ASP) and Java Server Pages (JSP) were developed. Asynchronous JavaScript and XML (Ajax) enables communication with the backend code without refreshing a web page. Ajax is a combination of different web development techniques to develop asynchronous client-side web applications. Using Ajax, data can be retrieved and sent to the server without interfering with the display of the DOM of the existing web page.

AngularJS is one of the really popular frameworks for client-side rendering. AngularJS allows you to extend HTML to create templates and enable a view and model for one-way or two-way data binding. In the real world, an application depends on the server-side code, which is known as backend, to execute the core business logic and communicate with the database. The AngularJS framework provides built-in support to communicate with a server. Data can be fetched either using an XMLHttpRequest object or JSON; in case of JSON, the request does not need to be asynchronous.

To make an Ajax request to the server, XMLHttpRequest makes a request, receives the server's response, checks for errors, and processes the server's response. This is a great deal of work for a simple, common, and frequently repeated task. The AngularJS API uses a promise interface; a promise symbolizes the final result of an operation. We can use a promise API to specify what to do when an operation finally succeeds or fails. The promise API is an established technique for server-side communication. In this technique, all requests made to a server are nonblocking or asynchronous requests, which means that, the response from the server will return some time in the near future. The promise interface makes sure that the response from the server is handled according to when it arrives from the server. In AngularJS, there are three functions then, success, and error that are used to handle the response from the server.

For example, we want to retrieve a car's information from the server. The web API that will be discussed in Chapter 5, Creating Applications Using AngularJS, Entity Framework, and ASP.NET Web API, is available at /Cars/getCarInfo and is required by the model as a parameter. The request from the client to fetch the car information from the server using AngularJS $http will look like the following:

app.controller('ctrlGetCarInfo', function ($scope, $http) {

var Url = '/Cars/getCarInfo';

 $http.get(Url, {params:{model:'Toyota'}

          }).success(function(data, status, headers, config)
            {
               <!--Do something when it is successful -->
          }).error(function(data, status, headers, config)
            {
              <! - - Handle the error - ->
            });
});

In the preceding code example, the client makes an Ajax request to the server in order to find out whether the car model used is Toyota. This request will not wait for the response from the server. Whenever, in the near future, the response is received from the server, the promise interface calls the appropriate function, success or error, depending on the server's response.

There are two different ways to implement $http in AngularJS. The first implementation is shown in the preceding code and the second approach is as follows:

app.controller('ctrlGetCarInfo', function ($scope, $http) {

    var Url = '/Cars/getCarInfo';

    $http({

            method: 'GET',
            url: Url,
            params:{model:'Toyota'}
        

    }).success(function (data, status, headers, config) {

        <!--Do something when it is successful -->

    }).error(function (data, status, headers, config) {

        <! - - Handle the error - ->
    });

});

There is no difference between the previous two approaches in terms of output. The difference between the preceding two approaches is that in the first approach, we used $http.get() and passed the parameters, such as Url and params, and this approach is known as a shortcut approach. In the second approach, we used $http and passed get as a parameter to the GET method instead of using $http.get(). It is a personal choice to use any approach. Personally, I prefer the second approach; we will use this approach for the rest of the chapter.

The $.ajax() method in the jQuery library and $http.get() in the AngularJS framework look almost the same. However, the implementation of these methods in both jQuery and AngularJS is different. jQuery uses its deferred library while AngularJS uses its $digest integrated version of the q library.

In AngularJS' promise API, success and error are special functions added to $http. In both of the preceding examples of retrieving data from the server with $http, we did not use the then function of $http. With promise, we can also use the then function, which will take the then function as the first parameter, and the error function, which will be the second parameter of $http, instead of using the success function as the first and the error function as the second parameter. The following code example demonstrates the use of the then function of $http:

app.controller('ctrlGetCarInfo', function ($scope, $http) {

    var Url = '/Cars/getCarInfo';

    $http({

            method: 'GET',
            url: Url,
            params:{model:'Toyota'}
        

    }).then(function (result) {

        Var list = result.data;

    }).error(function (data, status, headers, config) {

        <! - - Handle the error - ->
    });

});

In the preceding code, we replaced the .success function with the .then function. In this case, when we are using the .then function, it returns a new promise that will unwrap and normalize the AngularJS API response. However, while using the .success function, a new promise will not be returned; it will only return the original $http promise.

Configuring the $http request

AngularJS' built-in $http service is good enough to serve most purposes. AngularJS' built-in $http has the following methods:

  • $http.get(url, [config]): This is used to get data from the server where:
    • url: This is the absolute or relative URL path of destination request (required)
    • config: This is the configuration object (optional)
  • $http.head(url, [config]): This is used to get the full header information of the request where:
    • url: This is the absolute or relative URL path of destination request (required)
    • config: This is the configuration object (optional)
  • $http.post(url, data, [config]): This is used to post data to server where:
    • url: This is the absolute or relative URL path of destination request (required)
    • data: This is the data needed for post to the server (required)
    • config: This is the configuration object (optional)
  • $http.put(url, data, [config])
    • url: This is the absolute or relative URL path of destination request (required)
    • data: This is the data needs to post to the server (required)
    • config: This is the configuration object (optional)
  • $http.delete(url, [config]): This is used to delete data from the server where:
    • url: This is the absolute or relative URL path of destination request (required)
    • config: This is the configuration object (optional)
  • $http.jsonp(url, [config]): This is used to get JSON data from the server of a different domain where:
    • url: This is the absolute or relative URL path of destination request (required)
    • config: This is the configuration object (optional)
  • $http.patch(url, data, [config])
    • url: This is the absolute or relative URL path of destination request (required)
    • data: This is the data needs to post to the server (required)
    • config: This is the configuration object (optional)

We can customize the default $http configuration, such as to set the customer header, transform the client request and server response, set timeout instead of default timeout, enable cache and/or set the response type, and so on.

The following table shows the request arguments and their description for which we can use $http:

Argument

Description

method

This argument accepts string, HTTP method, such as GET, POST, PUT, DELETE, and so on.

url

This argument accepts string, the resource of the URL in the form of an absolute or relative path.

params

This argument accepts an object of strings or a string, which will become ?param1=value&param2=value after the URL. If the value is not a string value, then it will be JSONified.

data

This argument accepts string or object, data needs to be sent with request to server.

headers

This argument accept object, the HTTP header needs to be send to the server.

xsrfHeaderName

This argument accepts string, name of the HTTP header to populate with the XSRF token used for changing some settings to provide enhanced security.

xsrfCookieName

This argument accepts string, cookies containing the XSRF token.

transformRequest

This argument transforms function or any array of such functions. The transform function takes the HTTP response body and headers and returns it transformed. It is usually used to override the default transformation.

Cache

This argument accepts Boolean, $http will use the default cache if it is true, and $cacheFactory will be used in case it is false and built with $cacheFactory.

timeout

This argument accepts number, to set the timeout in milliseconds otherwise promise will abort the request when it is resolved.

withCredentials

This argument accepts Boolean, to set the credentials flag on the XHR object, which can be used as a request or response interceptor.

responseType

This argument accepts string, to set the response type.

The following table shows the response object properties:

Name

Description

data

This object return string, the transform function with response body

Status

This object return number, HTTP status code

Headers

This object return function, header getter function

Config

This object is used to generate the request

statusText

This object gives response of the HTTP text status

The following code shows how to implement custom configuration for $http. In the following example, we will use the post method of $http to post data on the server. If we want to post the data using the post method of $http, the content type needs to be changed to application/x-www-form-urlencoded. Instead of using the default content type in the header, we can change the content type in the header by changing the default configuration of $http as shown in the following code:

app.controller('ctrlSetCarInfo', function ($scope, $http) {

    var Url = '/Cars/setCarInfo';
    var newConfig = {
     
    timeout : 200,
        headers: {'Content-Type': 'application/x-www-form-urlencoded'}

    }

    $http({
            method: 'POST',
            url: Url,
            data:{'data':data}
        

    }).success(function (data, status, headers, config) {

        <!--Do something when it is successful -->

    }).error(function (data, status, headers, config) {

        <! - - Handle the error - ->
    });

});

In the preceding code example, we posted the data on the server using the $http service. Instead of using the built-in post method of $http, we customized the configuration. As you can see in the preceding code, we created a var newConfig variable and assigned timeout: 200 and headers: {content type: 'application/x-www-form-urlencoded'}. With this custom configuration, the timeout will occur after 200 milliseconds. The header of the request contains the content type of application/x-www-form-urlencoded. In a similar way, we can implement AngularJS' built-in $http methods.

Caching $http

In client-side application development, we are able to communicate with the server via the web API and populate the template (DOM) with data from the server's response. However, performance of the application is constantly affected if we get the data from the server, on each client's request, instead of caching the data. A cache is a constituent that stores the data on a client so that in future, the same client's request is served from the client cache instead of going back to server and receiving data from the server. The more a client's request is served from the cache, there is an increase in the overall application performance. Caching works with a key and a value combination; there is a key that will point to the data that is cached. When the data is requested from the client, the client first tries to find the data in the cache. If the assigned key is found in the cache, the client gets the data from the cache, which is known as a cache hit. Otherwise, if the data is not found in the cache, it is known as a cache miss and the client will request the data from the server.

In the AngularJS framework, the $http service has a built-in cache option that by default is turned off. When the cache option is off, the response from the server is not stored in the cache. However, what if we want to cache data for each request for the same resource? To do this, we need to set the $http request configuration property cache to true in order to use the default cache. The advantage of turning the cache option on for the $http service is that it will enable the $http service to prevent repeated requests to the server. When the $http cache property is true, the server response is stored in the cache. The next time the same request is made, the response is served from the cache instead of sending a request to the server. It is notable that even though the response is served from the cache, the delivery of the data will still be asynchronous.

If the client makes multiple GET requests for the same resource, only the first request gets the data from the server and is stored in the client cache. The following requests will fetch the data from the cache, which will contain the same data as the first request.

The following code shows how to set the $http configuration property cache to true:

app.controller('ctrlGetCarInfo', function ($scope, $http) {

    var Url = '/Cars/getCarInfo';

    $http({

            method: 'GET',
            url: Url,
            cache:true,
            params:{model:'Toyota'}
        

    }).success(function (data, status, headers, config) {

        <!--Do something when it is successful -->

    }).error(function (data, status, headers, config) {

        <! - - Handle the error - ->
    });

});

<!—OR --> 

app.controller('ctrlGetCarInfo', function ($scope, $http) {

var Url = '/Cars/getCarInfo';

 $http.get(Url, {params:{model:'Toyota'}, cache:true

          }).success(function(data, status, headers, config)
            {
               <!--Do something when it is successful -->
          }).error(function(data, status, headers, config)
            {
              <! - - Handle the error - ->
            });
});

In the preceding code, we demonstrated how to set the client cache for server-side content using the $http caching mechanism.

Transforming request and response

When we make a request to or receive a response from the server, the $http service allows us to define transformation functions in the $http configuration property for both the request and response. However, these options are optional; by default, the $http service is set to handle JSON. JSON is a very malleable data format. It can contain randomly nested data structures.

In the AngularJS framework, when we are posting data using the $http service, by default, the data will be serialized with JSON and sent to the server with the content type of application/json. However, if we want to post data with a different content type, we can override the default $http service transformation. Both the $http request and response can be transformed using the $http service's transform functions, transformRequest and transformResponse. These $http configuration properties are single functions that return the transformed data or an array of such transformation functions, which allows us to make a new transformation in the transformation chain.

The default transformation of request and response of $http is as follows:

  • Request transformation (transformRequest):
    • The data will be serialized in JSON if it is present in the request property of the configuration object.
  • Response transformation (transformResponse):
    • If the JSON response is received from the server, deserialize it using the JSON parser. If XSRF is received, strip it.

Both the request and response transformation can be achieved within the $http configuration property, which has access to the request and response header collection and nonserialized data. The purpose of the transformation is to update the header information and to return the updated data that will be injected in the underlying XMLHttpRequest object.

If you want to update the default transformation of a single request and response, then provide the transformRequest and/or transformResponse properties of the configuration object passed into $http, as shown in the following code:

function appendTransform(defaults, transform) { 

 <!-- We can't guarantee that the default transformation is an array -->

defaults = angular.isArray(defaults) ? defaults : [defaults]; 

<!--Append the new transformation to the defaults return -->

defaults.concat(transform); 

} 

var Url = '/Cars/getCarInfo';

$http({ url: Url, method: 'GET', 

transformResponse:appendTransform($http.defaults.transformResponse, 

function(value) { 

return doTransform(value); 

}) 

});

If you have to update the default transformation of a whole application, best practice is to make a change to transformRequest and/or transformResponse in the application configuration instead of changing each request, as shown in the following code:

var app = angular.model('myApp',[]);

app.config(['$httpProvider', function($httpProvider) {

    $httpProvider.defaults.transformResponse = function(data) {

      return performSomeTransformation(data);

    };

  }])

In the preceding code, we updated the application's global configuration for transformation instead of updating the transformation for each request and/or response of $http.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset