private IEnumerable <LinkDTO> CreateLinksForSupermarkets(SupermarketResourceParameters supermarketResourceParameters,
                                                                 bool hasNext, bool hasPrevious)
        {
            var links = new List <LinkDTO>();

            // self
            links.Add(
                new LinkDTO(CreateSupermarketResourceUri(supermarketResourceParameters,
                                                         ResourceUriType.Current)
                            , "self", "GET"));

            if (hasNext)
            {
                links.Add(
                    new LinkDTO(CreateSupermarketResourceUri(supermarketResourceParameters,
                                                             ResourceUriType.NextPage),
                                "nextPage", "GET"));
            }

            if (hasPrevious)
            {
                links.Add(
                    new LinkDTO(CreateSupermarketResourceUri(supermarketResourceParameters,
                                                             ResourceUriType.PreviousPage),
                                "previousPage", "GET"));
            }

            return(links);
        }
        private string CreateSupermarketResourceUri(
            SupermarketResourceParameters supermarketResourceParameters,
            ResourceUriType type)
        {
            switch (type)
            {
            case ResourceUriType.PreviousPage:
                return(_urlHelper.Link("GetSupermarkets",
                                       new
                {
                    fields = supermarketResourceParameters.Fields,
                    orderBy = supermarketResourceParameters.OrderBy,
                    searchQuery = supermarketResourceParameters.SearchQuery,
                    pageNumber = supermarketResourceParameters.PageNumber - 1,
                    pageSize = supermarketResourceParameters.PageSize
                }));

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

            case ResourceUriType.Current:
            default:
                return(_urlHelper.Link("GetSupermarkets",
                                       new
                {
                    fields = supermarketResourceParameters.Fields,
                    orderBy = supermarketResourceParameters.OrderBy,
                    searchQuery = supermarketResourceParameters.SearchQuery,
                    pageNumber = supermarketResourceParameters.PageNumber,
                    pageSize = supermarketResourceParameters.PageSize
                }));
            }
        }
        public PagedList <Supermarket> GetAllSupermarkets(SupermarketResourceParameters supermarketResourceParameters)
        {
            //var collectionBeforePaging = _context.Supermarkets.OrderBy(s => s.Location).AsQueryable();

            var collectionBeforePaging =
                _context.Supermarkets.ApplySort(supermarketResourceParameters.OrderBy,
                                                _propertyMappingService.GetPropertyMapping <SupermarketDTO, Supermarket>());

            if (!string.IsNullOrEmpty(supermarketResourceParameters.SearchQuery))
            {
                // trim & ignore casing
                var searchQueryForWhereClause = supermarketResourceParameters.SearchQuery
                                                .Trim().ToLowerInvariant();

                collectionBeforePaging = collectionBeforePaging
                                         .Where(s => s.Location.ToLowerInvariant().Contains(searchQueryForWhereClause));
            }

            return(PagedList <Supermarket> .Create(collectionBeforePaging,
                                                   supermarketResourceParameters.PageNumber,
                                                   supermarketResourceParameters.PageSize));
        }
        public IActionResult GetSupermarkets(SupermarketResourceParameters supermarketResourceParameters,
                                             [FromHeader(Name = "Accept")] string mediaType)
        {
            // check mappings are valid
            if (!_propertyMappingService.ValidMappingExistsFor <SupermarketDTO, Supermarket>
                    (supermarketResourceParameters.OrderBy))
            {
                return(BadRequest());
            }

            // check all fields are valid
            if (!_typeHelperService.TypeHasProperties <SupermarketDTO>
                    (supermarketResourceParameters.Fields))
            {
                return(BadRequest());
            }

            var supermarketsFromRepo = _supermarketRepository.GetAllSupermarkets(supermarketResourceParameters);

            var supermarkets = Mapper.Map <IEnumerable <SupermarketDTO> >(supermarketsFromRepo);

            if (mediaType == "application/vnd.idp.hateoas+json")
            {
                // Pagination
                var paginationMetadata = new
                {
                    totalCount  = supermarketsFromRepo.TotalCount,
                    pageSize    = supermarketsFromRepo.PageSize,
                    currentPage = supermarketsFromRepo.CurrentPage,
                    totalPages  = supermarketsFromRepo.TotalPages
                };

                Response.Headers.Add("X-Pagination",
                                     JsonConvert.SerializeObject(paginationMetadata));

                var links = CreateLinksForSupermarkets(supermarketResourceParameters,
                                                       supermarketsFromRepo.HasNext, supermarketsFromRepo.HasPrevious);

                var shapedSupermarkets = supermarkets.ShapeData(supermarketResourceParameters.Fields);

                var shapedSupermarketsWithLinks = shapedSupermarkets.Select(supermarket =>
                {
                    var supermarketAsDictionary = supermarket as IDictionary <string, object>;
                    var supermarketLinks        = CreateLinksForSupermarket(
                        (int)supermarketAsDictionary["SupermarketId"], supermarketResourceParameters.Fields);

                    supermarketAsDictionary.Add("links", supermarketLinks);

                    return(supermarketAsDictionary);
                });

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

                return(Ok(linkedCollectionResource));
            }
            else
            {
                var previousPageLink = supermarketsFromRepo.HasPrevious ?
                                       CreateSupermarketResourceUri(supermarketResourceParameters,
                                                                    ResourceUriType.PreviousPage) : null;

                var nextPageLink = supermarketsFromRepo.HasNext ?
                                   CreateSupermarketResourceUri(supermarketResourceParameters,
                                                                ResourceUriType.NextPage) : null;

                var paginationMetadata = new
                {
                    previousPageLink,
                    nextPageLink,
                    totalCount  = supermarketsFromRepo.TotalCount,
                    pageSize    = supermarketsFromRepo.PageSize,
                    currentPage = supermarketsFromRepo.CurrentPage,
                    totalPages  = supermarketsFromRepo.TotalPages
                };

                Response.Headers.Add("X-Pagination",
                                     JsonConvert.SerializeObject(paginationMetadata));

                return(Ok(supermarkets.ShapeData(supermarketResourceParameters.Fields)));
            }
        }