private IEnumerable <LinkDto> CreateLinksForApplications(
            ApplicationsResourceParameters applicationsResourceParameters,
            bool hasNext, bool hasPrevious)
        {
            var links = new List <LinkDto>();

            // self
            links.Add(
                new LinkDto(CreateApplicationsResourceUri(applicationsResourceParameters,
                                                          ResourceUriType.Current)
                            , "self", "GET"));

            if (hasNext)
            {
                links.Add(
                    new LinkDto(CreateApplicationsResourceUri(applicationsResourceParameters,
                                                              ResourceUriType.NextPage),
                                "nextPage", "GET"));
            }

            if (hasPrevious)
            {
                links.Add(
                    new LinkDto(CreateApplicationsResourceUri(applicationsResourceParameters,
                                                              ResourceUriType.PreviousPage),
                                "previousPage", "GET"));
            }

            return(links);
        }
        //public IEnumerable<Application> GetApplications(ApplicationsResourceParameters applicationsResourceParameters)
        public PagedList <Application> GetApplications(ApplicationsResourceParameters applicationsResourceParameters)
        {
            // BEFORE APPLYING SORTING
            //var collectionBeforePaging = _applicationInfoContext.Applications
            //    .Include(a => a.CountryOfResidence)
            //    .Include(a => a.CountryOfBirth)
            //    .OrderBy(a => a.Id)
            //    .ThenBy(a => a.Gender)
            //    .AsQueryable();

            // Apply Sorting
            var collectionBeforePaging =
                _applicationInfoContext.Applications.ApplySort(applicationsResourceParameters.OrderBy,
                                                               _propertyMappingService.GetPropertyMapping <ApplicationDto, Application>());

            // Filtering
            // http://localhost:63292/api/applications?gender=Female
            if (!string.IsNullOrEmpty(applicationsResourceParameters.Gender))
            {
                // trim & ignore casing
                var genreForWhereClause = applicationsResourceParameters.Gender
                                          .Trim().ToLowerInvariant();
                collectionBeforePaging = collectionBeforePaging
                                         .Where(a => a.Gender.ToLowerInvariant() == genreForWhereClause);
            }

            // Searching
            //http://localhost:63292/api/applications?searchQuery=vaibhav
            if (!string.IsNullOrEmpty(applicationsResourceParameters.SearchQuery))
            {
                // trim & ignore casing
                var searchQueryForWhereClause = applicationsResourceParameters.SearchQuery
                                                .Trim().ToLowerInvariant();

                collectionBeforePaging = collectionBeforePaging
                                         .Where(a => a.Gender.ToLowerInvariant().Contains(searchQueryForWhereClause) ||
                                                a.FirstName.ToLowerInvariant().Contains(searchQueryForWhereClause) ||
                                                a.LastName.ToLowerInvariant().Contains(searchQueryForWhereClause));
            }

            // Adding Page Number and Page Size
            // http://localhost:63292/api/applications?pageNumber=2&pageSize=5
            return(PagedList <Application> .Create(collectionBeforePaging,
                                                   applicationsResourceParameters.PageNumber,
                                                   applicationsResourceParameters.PageSize));

            //return _applicationInfoContext.Applications
            //    .Include(a => a.CountryOfResidence)
            //    .Include(a => a.CountryOfBirth)
            //    .OrderBy(a => a.Id)
            //    //.Include(e => e.ApplicationQualifications)
            //    //.ThenInclude(q => q.Qualification)
            //    .ToList();
        }
        private string CreateApplicationsResourceUri(
            ApplicationsResourceParameters applicationsResourceParameters,
            ResourceUriType type)
        {
            switch (type)
            {
            case ResourceUriType.PreviousPage:
                return(_urlHelper.Link("GetApplications",
                                       new
                {
                    fields = applicationsResourceParameters.Fields,
                    orderBy = applicationsResourceParameters.OrderBy,
                    searchQuery = applicationsResourceParameters.SearchQuery,
                    gender = applicationsResourceParameters.Gender,
                    pageNumber = applicationsResourceParameters.PageNumber - 1,
                    pageSize = applicationsResourceParameters.PageSize
                }));

            case ResourceUriType.NextPage:
                return(_urlHelper.Link("GetApplications",
                                       new
                {
                    fields = applicationsResourceParameters.Fields,
                    orderBy = applicationsResourceParameters.OrderBy,
                    searchQuery = applicationsResourceParameters.SearchQuery,
                    gender = applicationsResourceParameters.Gender,
                    pageNumber = applicationsResourceParameters.PageNumber + 1,
                    pageSize = applicationsResourceParameters.PageSize
                }));

            default:
                return(_urlHelper.Link("GetApplications",
                                       new
                {
                    fields = applicationsResourceParameters.Fields,
                    orderBy = applicationsResourceParameters.OrderBy,
                    searchQuery = applicationsResourceParameters.SearchQuery,
                    gender = applicationsResourceParameters.Gender,
                    pageNumber = applicationsResourceParameters.PageNumber,
                    pageSize = applicationsResourceParameters.PageSize
                }));
            }
        }
        public IActionResult GetApplications(
            ApplicationsResourceParameters applicationsResourceParameters, //  AuthorsResourceParameters => URL Optional Input Parameters for Paging and filtering
            [FromHeader(Name = "Accept")] string mediaType                 //  HATEOAS and Content Negotiation => Accept : //application/vnd.vaibhav.hateoas+json
            )
        {
            try
            {
                // Check if non existing property has been requested
                //  This is dynamic Mapping of AuthorDto to Entity.Author
                // e.g. http://localhost:6058/api/applications?orderBy=dateofbirth   => In this case => 'dateofbirth' does not exist
                if (!_propertyMappingService.ValidMappingExistsFor <ApplicationDto, Application>
                        (applicationsResourceParameters.OrderBy))
                {
                    return(BadRequest());
                }

                if (!_typeHelperService.TypeHasProperties <ApplicationDto>
                        (applicationsResourceParameters.Fields))
                {
                    return(BadRequest());
                }
                var applicationsFromRepo = _applicationInfoRepository.GetApplications(applicationsResourceParameters);
                var results = Mapper.Map <IEnumerable <ApplicationDto> >(applicationsFromRepo);

                #region Wrapping  HATEOAS (Dynamic Approach) in Content Negotiation => Accept : application/vnd.vaibhav.hateoas+json
                if (mediaType == "application/vnd.vaibhav.hateoas+json")
                {
                    var paginationMetadata = new
                    {
                        totalCount  = applicationsFromRepo.TotalCount,
                        pageSize    = applicationsFromRepo.PageSize,
                        currentPage = applicationsFromRepo.CurrentPage,
                        totalPages  = applicationsFromRepo.TotalPages
                    };
                    Response.Headers.Add("X-Pagination",
                                         Newtonsoft.Json.JsonConvert.SerializeObject(paginationMetadata));

                    #region Supporting HATEOAS (Dynamic Approach)
                    var links = CreateLinksForApplications(applicationsResourceParameters,
                                                           applicationsFromRepo.HasNext, applicationsFromRepo.HasPrevious);
                    var shapedApplications          = results.ShapeData(applicationsResourceParameters.Fields);
                    var shapedApplicationsWithLinks = shapedApplications.Select(application =>
                    {
                        var applicationsAsDictionary = application as IDictionary <string, object>;
                        var authorLinks = CreateLinksForApplication(
                            (Int32)applicationsAsDictionary["Id"], applicationsResourceParameters.Fields);

                        applicationsAsDictionary.Add("links", authorLinks);

                        return(applicationsAsDictionary);
                    });

                    var linkedCollectionResource = new
                    {
                        value = shapedApplicationsWithLinks,
                        links = links
                    };

                    return(Ok(linkedCollectionResource));

                    #endregion
                }
                #endregion
                #region Accept : application/json
                else
                {
                    var previousPageLink = applicationsFromRepo.HasPrevious ?
                                           CreateApplicationsResourceUri(applicationsResourceParameters,
                                                                         ResourceUriType.PreviousPage) : null;

                    var nextPageLink = applicationsFromRepo.HasNext ?
                                       CreateApplicationsResourceUri(applicationsResourceParameters,
                                                                     ResourceUriType.NextPage) : null;

                    var paginationMetadata = new
                    {
                        totalCount       = applicationsFromRepo.TotalCount,
                        pageSize         = applicationsFromRepo.PageSize,
                        currentPage      = applicationsFromRepo.CurrentPage,
                        totalPages       = applicationsFromRepo.TotalPages,
                        previousPageLink = previousPageLink,
                        nextPageLink     = nextPageLink
                    };
                    Response.Headers.Add("X-Pagination",
                                         Newtonsoft.Json.JsonConvert.SerializeObject(paginationMetadata));
                    return(Ok(results.ShapeData(applicationsResourceParameters.Fields)));
                }
                #endregion

                //return Ok(results.ShapeData(applicationsResourceParameters.Fields));

                // Before SHAPING of data
                //return Ok(results);
            }
            catch (Exception e)
            {
                _logger.LogInformation(e.Message);
                throw;
            }
        }