Pagination in AngularJS by resolving CORS in Web API with ASP.NET Core 1.0 MVC

Rajnilari2015
Posted by in ASP.NET Core category on for Beginner level | Points: 250 | Views : 684 red flag
Rating: 4 out of 5  
 1 vote(s)

In this article we will look into how to perform pagination in AngularJS by resolving CORS in Web API with ASP.NET Core 1.0 MVC in a step by step manner.


 Download source code for Pagination in AngularJS by resolving CORS in Web API with ASP.NET Core 1.0 MVC

Introduction

WebAPI is a framework for building HTTP services that can be consumed by a wide range of clients like browsers, mobiles, desktop, tablets etc. AngularJS, on the other hand, is use for service consumption and presenting the data in the HTML templates. In one of the earlier article we have seen how to perform CRUD operations using WebAPI with ASP.NET Core 1.0 MVC using Google PostMan as the client. In this article we will look into how to perform pagination in AngularJS by resolving CORS in Web API with ASP.NET Core 1.0 MVC in a step by step manner.

Creating the WebAPI project

Fire up Visual Studio 2015 and then File -> New -> Project -> Web -> ASP.NET Core Web Applications(.NET Core).Choose the target Framework as .Net Framework 4.6.1.

The next screen that pops up display's a list of templates and we need to choose Web API template.

ASP.NET Core 1.0 includes only Web API and MVC but not SignalR or Web Pages yet. We choose the Web API and Click "OK" button and here is our "Welcome Screen"

Create a Model Class

Now let us first create a folder by the name "Model". Then add EmployeeRelatedInformation and Employee model as under

using System.Collections.Generic;

namespace WebAPI_Asp.netCore.Model
{
    public class Employee
    {
        public int EmployeeID { get; set; }
        public string EmployeeName { get; set; }
        public string EmailAddress { get; set; }
        public string PhoneNumber { get; set; }
    }

    public class EmployeeRelatedInformation
    {
        public int EmployeeRecordCount { get; set; }
        public List<Employee> Employees { get; set; }
    }
}

Our Employee model is a simple Employee Class which has some scalar properties like EmployeeID,EmployeeName,EmailAddress,PhoneNumber This Employee model represents the Employee related data model in our application. The EmployeeRelatedInformation Class has two properties viz. EmployeeRecordCount that holds the Total Employee Count and Employees that provides the Employee information.

Create the Repository objects

The repository objects are responsible for encapsulating the data layer. It contains logic for retrieving data and mapping it to an entity model.

Now let us first create a folder by the name "Repository" and first create an interface say IEmployeeRepository.cs inside that folder. This interface is responsible for the Pagination operation

using System.Collections.Generic;
using WebAPI_Asp.netCore.Model;

namespace WebAPI_Asp.netCore.Repository
{
    public interface IEmployeeRepository
    {
        List<Employee> GetEmployees();
        List<Employee> GetEmployeesForPagination(int startIndex, int endIndex);
     }        
}

Next we need to have a concrete repository class which will implement the IEmployeeRepository interface. Let us add EmployeeRepository.cs class that will implement the IEmployeeRepository and will provide the concrete implementation for the same.

using System.Collections.Generic;
using System.Linq;
using WebAPI_Asp.netCore.Model;

namespace WebAPI_Asp.netCore.Repository
{
    public class EmployeeRepository : IEmployeeRepository
    {
        /// <summary>
        /// Function: GetEmployees
        /// Get the Employee Records
        /// </summary>
        /// <returns></returns>
        public List<Employee> GetEmployees()
        {
            var empList = new List<Employee>();
            Enumerable
                .Range(1, 20)
                .ToList()
                .ForEach(
                            i => empList.Add(new Employee
                            {
                                EmployeeID = i,
                                EmployeeName = "Employee" + i,
                                EmailAddress = "Employee" + i + "@test.com",
                                PhoneNumber = "PhoneNumber" + i
                            })
                        );
            return empList;            
        }

        /// <summary>
        /// Function: GetEmployees
        /// Get the Employee Records for the range
        /// </summary>
        /// <param name="startIdx"></param>
        /// <param name="endIdx"></param>
        /// <returns></returns>
        public List<Employee> GetEmployeesForPagination(int startIdx, int endIdx)
        {
            return GetEmployees()
                    .Skip(startIndex - 1)
                    .Take(endIndex - (startIndex - 1))
                    .ToList();
        }
    }
}

The EmployeeRepository is a concrete implementation. In the GetEmployees() method, we fetch the Employee Records. These 20 records are created at runtime using Enumerable.Range(int start, int count) function. The GetEmployeesForPagination takes two parameters vix. StartIndex and EndIndex. It takes the whole collection and perform the pagination based on the range supplied. For example, we want to get the records from 1 to 5. So, startIndex = 1 and endIndex=5. Now GetEmployees() will return the whole 20 records. The Skip function will skip startIndex - 1= 1-1= 0 records. The Take function will take endIndex - (startIndex - 1)=5-(1-1)=5-0=5 records.

Register the repository to the ASP.NET Core's dependency injection

Instead of instantiating the EmployeeRepository inside the controller, we will register the repository to the built-in ASP.NET Core's dependency injection. For that, let's open the Startup.cs file and in the ConfigureServices method, add the below code

public void ConfigureServices(IServiceCollection services)
{
    // Add framework services.           
    services.AddSingleton<IEmployeeRepository, EmployeeRepository>();
}

Now expand the Controllers folder and create EmployeeController.cs and add the following code

using Microsoft.AspNetCore.Mvc;
using WebAPI_Asp.netCore.Model;
using WebAPI_Asp.netCore.Repository;

namespace WebAPI_Asp.netCore.Controllers
{
    [Route("Employee")]
    public class EmployeeController : Controller
    {
        public EmployeeController(IEmployeeRepository employees)
        {
            EmployeeRecords = employees;
        }
        public IEmployeeRepository EmployeeRecords { get; set; }  

        [HttpGet]
        [Route("EmployeeRecordsForPagination")]        
        public EmployeeRelatedInformation GetEmployeeRecordsForPagination(int startIndex, int endIndex)
        {
            EmployeeRelatedInformation eri = new EmployeeRelatedInformation();
            eri.EmployeeRecordCount = EmployeeRecords.GetEmployees().Count;
            eri.Employees = EmployeeRecords.GetEmployeesForPagination(startIndex, endIndex);
            return eri;
        }
    }
}

Now we can test the API Services of the EmployeeController.cs through PostMan.

Open PostMan and write the URL(http://localhost:7625/Employee/EmployeeRecordsForPagination?startIndex=1&endIndex=5), and choose Http method to GET and click on Send button. The result is as under

So, our pagination is working.

Consuming services through AngularJS

Now, it's time to consume the web services through AngularJS and to bind the data.

Step 1: Create an Application Module (employeeModule.js)

For this to happen, let us first create a employeeModule.js file whose content is as under

//creating an application module
var employeeAppModule = angular.module("employeeApp", []);

This js file basically creates an application module. Since AngularJS follows modular approach, so the modules are used to separate the logics like services, controllers, application etc. This on the other hand keep the code clean. Here we have declared an application employeeApp module using angular.module function.

Step 2: Create the Service file (employeeService.js)

As a next step we will create the service file (employeeService.js) as under

employeeAppModule.service('EmployeeService', ['$http', function ($http) {

        var employeeService = {};
 
        var urlBase = 'http://localhost:7625/Employee'; //the base for the Employee Resource
        
        //invoke the service
        employeeService.getEmployees = function (startIDX,endIDX) {
                        
                var uRL = urlBase + '/EmployeeRecordsForPagination?startIndex='+startIDX+'&endIndex='+endIDX; 
                return $http.get(uRL);
        };
 
    //returns the record obtained from the service
    return employeeService;
}]);

The service method is use to create the service. It is lazily instantiated such that angular will only instantiate a service when the component is dependent on it.It is wired using dependency injection(which we will look into the Controller part).The service method does not return anything.

We have created a function by the name getEmployees that uses the $http for fetching the server record that is assigned to the variable employeeService. The function takes two arguments viz.startIDX,endIDX that are passed from the controller. Finally we return the employeeService object.

Step 3: Create the Controller file (employeeController.js)

Let us look into the employeeController.js

//The below code will fetch the data from EmployeeService and will pass to the $scope variable 

employeeAppModule.controller('EmployeeCtrl', function ($scope, EmployeeService) //injected the EmployeeService
{
    //record setting properties
    $scope.pageSize = 5;
    $scope.startIndex=1;
    $scope.endIndex = $scope.pageSize;

    //these properties control the previous and next buttons enabling behaviour
    $scope.disableStart=true;
    $scope.disableEnd=false;

    //this property will store the total employee records count
    $scope.employeeRecordCount = 0;   
    
    //this property will store the employee records
    $scope.empRecords = null;

    //invoke this function when page loads. So it is kept inside the constructor
    getEmployeeRecords($scope.startIndex,$scope.endIndex); 
 
    //fetch employee records based on the range passed
    function getEmployeeRecords(startIDX,endIDX) 
    {               
        EmployeeService.getEmployees(startIDX,endIDX) //invoking the getEmployees(startIDX,endIDX) method of the EmployeeService

            .success(function (data) { // case when records found successfully
                            
                $scope.employeeRecordCount = data.employeeRecordCount;
                $scope.empRecords = data.employees;
 
            })

            .error(function (data, status) { // if something goes wrong

                console.error('failure loading the employee record', status, data);
                $scope.empRecords = { }; //return blank record if something goes wrong
 
            });
    }

    //this function is invoked when Previous button is clicked
    $scope.prevEmployeeRecords = function(){
        
        $scope.startIndex=$scope.startIndex - $scope.pageSize ;
        $scope.endIndex=$scope.endIndex - $scope.pageSize ; 

        if($scope.startIndex==1){ //when the first index is reached, then disable the Previous button.
            $scope.disableStart = true;
            getEmployeeRecords($scope.startIndex,$scope.endIndex);
        
        } else { //allow the Next button to proceed since there is some record to navigate
            
            $scope.disableEnd = false;
            getEmployeeRecords($scope.startIndex,$scope.endIndex); 
        }
      } 

    //this function is invoked when Next button is clicked
    $scope.nextEmployeeRecords = function(){

        $scope.startIndex=$scope.startIndex + $scope.pageSize ;
        $scope.endIndex=$scope.endIndex + $scope.pageSize ;
        
        if($scope.endIndex === $scope.employeeRecordCount){ //when the last index is reached, then disable the Next button.
            
            $scope.disableEnd = true;
            getEmployeeRecords($scope.startIndex,$scope.endIndex); 
        } else { //allow the Previous button to proceed since there is some record to navigate
            $scope.disableStart = false;
            getEmployeeRecords($scope.startIndex,$scope.endIndex);
        }
    } 
});

The code pattern is a typical MVC one. First we have created the employeeAppModule.It is an Application Module that is use to initialize the application with controller which is EmployeeCtrl in our case.

Next we have created a controller module EmployeeCtrl and injected the EmployeeService into it using the Dependency Injection pattern of AngularJS.

For reading data from the Web API, we are invoking the getEmployeeRecords(startIDX,endIDX) method of the EmployeeService by passing the range where in the success case we are setting the data to the $scope.empRecords variable. We are also setting $scope.employeeRecordCount for the total employee record count. If anything goes wrong while reading the data, we are setting the $scope.empRecords = { } as empty.

The $scope.employees variable acts as a glue for carrying the data from the controller to the view (i.e. html part).

The function prevEmployeeRecords is invoked when Previous button is clicked. Likewise, the function nextEmployeeRecords is invoked when Next button is clicked.

Step 4: Create the View (index.html)

Now comes the binding part.Let us now look into the code

<!DOCTYPE html>
<html>
<head>
  <script data-require="angular.js@1.4.0-beta.6" data-semver="1.4.0-beta.6" src="https://code.angularjs.org/1.4.0-beta.6/angular.js">
  </script> 
  <script src="employeeModule.js"></script>
 <script src="employeeController.js"></script>
 <script src="employeeService.js"></script>

</head>

<body ng-app="employeeApp">
        <div><h2><font color="blue"><u>Display Employee Records</u></font></h2> </div>
        <div ng-controller="EmployeeCtrl">  
            <table border="1">
                <tr bgcolor="gray">
                      
                      <td>Employee ID</td>  
                      <td>Employee Name</td>
                      <td>Email</td>
                      <td>Phone Number</td>                   
                </tr>
                <tr ng-repeat="employee in empRecords">
                      <td><span>{{employee.employeeID}}</span></td> 
                      <td><span>{{employee.employeeName}}</span></td>                         
                      <td><span>{{employee.emailAddress}}</span></td>   
                      <td><span>{{employee.phoneNumber}}</span></td>
                </tr>             
            </table>
            <table border="1">
            <tr>
                <td><input type="button" id="btnPrev" ng-disabled=disableStart value="<" ng-click="prevEmployeeRecords()" /></td>
                <td>
                    <input type="button" id="btnNext" ng-disabled=disableEnd value=">" ng-click="nextEmployeeRecords()"/>        
                </td>
            </tr>
          </table>
        </div>        
    </body>
</html>

Run the application

Finally we can run the application. But we encounter the below problem

The message

XMLHttpRequest cannot load http://localhost:7625/Employee/EmployeeRecordsForPagination?startIndex=1&endIndex=5. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access.

indicates that we need to Enable Cross-Origin Requests in ASP.NET Web API

Resolving CORS in Asp.net Core Web API

Let's go back to the WebAPI project, open Startup.cs file. Let's enable CORS by adding AddCors method in the ConfigureServices method as shown under

public void ConfigureServices(IServiceCollection services)
{ 
    //Add the CORS services 
    services.AddCors();
}

This method adds cross-origin resource sharing services to the specified Microsoft.Extensions.DependencyInjection.IServiceCollection. General sysntax is

public static IServiceCollection AddCors(this IServiceCollection services);

The ConfigureServices method gets called by the runtime inorder to add services to the container.

As a next step , we need to add CORS middleware to the web application pipeline to allow cross domain requests. For this to happen, we need also to set allowed origins, headers and methods to the UseCors method in the Configure method as shown below

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{          
    app.UseCors(builder => builder.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod());
}

The Configure method is use to configure the HTTP request pipeline at runtime.

The complete Startup.cs looks as under

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using WebAPI_Asp.netCore.Repository;

namespace WebAPI_Asp.netCore
{
    public class Startup
    {
        public Startup(IHostingEnvironment env)
        {
            var builder = new ConfigurationBuilder()
                .SetBasePath(env.ContentRootPath)
                .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
                .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
                .AddEnvironmentVariables();
            Configuration = builder.Build();
        }

        public IConfigurationRoot Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            // Add framework services.
            services.AddMvc();
            services.AddSingleton<IEmployeeRepository, EmployeeRepository>();

            //Add the CORS services 
            services.AddCors();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
        {           
            loggerFactory.AddConsole(Configuration.GetSection("Logging"));
            loggerFactory.AddDebug();

            app.UseCors(builder => builder.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod());

            app.UseMvc();
            
        }
    }
}

Now run the application again and the output is as under(for range of 1-5)

For the range(16-20), the output is as under

Reference

Enabling Cross-Origin Requests (CORS)

Conclusion

In this article, we have learnt about resolving CORS in Asp.net MVC Core 1.0 with Web API by demonstrating paginaton in AngularJS. Hope this will be helpful. Thanks for reading. Zipped file attached.

Recommendation
Read Let's Explore ASP.NET Core 1.0 briefly after this article.
Page copy protected against web site content infringement by Copyscape

About the Author

Rajnilari2015
Full Name: Niladri Biswas (RNA Team)
Member Level: Platinum
Member Status: Member,MVP
Member Since: 3/17/2015 2:41:06 AM
Country: India
-- Thanks & Regards, RNA Team


Login to vote for this post.

Comments or Responses

Login to post response

Comment using Facebook(Author doesn't get notification)