private IEnumerable <LinkDto> CreateLinksForPersons(PersonsResourceParameters personsResourceParameters, bool hasNext, bool hasPrevious) { var links = new List <LinkDto>(); links.Add(new LinkDto(CreatePersonsResourceUri(personsResourceParameters, ResourceUriType.Current), "self", "GET")); if (hasNext) { links.Add(new LinkDto(CreatePersonsResourceUri(personsResourceParameters, ResourceUriType.NextPage), "nextPage", "GET")); } if (hasPrevious) { links.Add(new LinkDto(CreatePersonsResourceUri(personsResourceParameters, ResourceUriType.PreviousPage), "previousPage", "GET")); } return(links); }
public PagedList <Person> GetPersons(PersonsResourceParameters personsResourceParameters) { if (personsResourceParameters == null) { throw new ArgumentNullException(nameof(personsResourceParameters)); } //if (string.IsNullOrWhiteSpace(personsResourceParameters.Gender) && string.IsNullOrWhiteSpace(personsResourceParameters.SearchQuery)) //{ // return GetPersons(); //} var collection = _context.People as IQueryable <Person>; if (!string.IsNullOrWhiteSpace(personsResourceParameters.Gender)) { var gender = personsResourceParameters.Gender.Trim(); collection = collection.Where(a => a.Gender == gender); } if (!string.IsNullOrWhiteSpace(personsResourceParameters.SearchQuery)) { var searchQuery = personsResourceParameters.SearchQuery.Trim(); collection = collection.Where(a => a.Gender.Contains(searchQuery) || a.Email.Contains(searchQuery) || a.FirstName.Contains(searchQuery) || a.LastName.Contains(searchQuery) || a.Address.Contains(searchQuery)); } if (!string.IsNullOrWhiteSpace(personsResourceParameters.OrderBy)) { //collection = collection.OrderBy(a => a.FirstName).ThenBy(a => a.LastName); // Get property mapping dictionary var personPropertyMappingDictionary = _propertyMappingService.GetPropertyMapping <PersonDto, Person>(); collection = collection.ApplySort(personsResourceParameters.OrderBy, personPropertyMappingDictionary); } // It is important to add pagination last because we want to apply the pagination // on the filtered and searched collection. And if we did it first we would be searching and // filtering to only a small set of data, which would not return all the results, which is incorrect // The -1 insures that if we want to get page 2, the amount of items on page 1 will be skipped // Due to the Deferred Execution the query is only executed here because the IQueryably only // stores the queries. Only when we do a for loop, ToList..., or singleton queries (average, first) return(PagedList <Person> .Create(collection, personsResourceParameters.PageNumber, personsResourceParameters.PageSize)); //collection //.Skip(personsResourceParameters.PageSize * (personsResourceParameters.PageNumber - 1)) //.Take(personsResourceParameters.PageSize) //.ToList(); }
private string CreatePersonsResourceUri(PersonsResourceParameters personsResourceParameters, ResourceUriType type) { switch (type) { case ResourceUriType.PreviousPage: return(Url.Link("GetPersons", new { fields = personsResourceParameters.Fields, orderBy = personsResourceParameters.OrderBy, pageNumber = personsResourceParameters.PageNumber - 1, pageSize = personsResourceParameters.PageSize, gender = personsResourceParameters.Gender, searchQuery = personsResourceParameters.SearchQuery })); case ResourceUriType.NextPage: return(Url.Link("GetPersons", new { fields = personsResourceParameters.Fields, orderBy = personsResourceParameters.OrderBy, pageNumber = personsResourceParameters.PageNumber + 1, pageSize = personsResourceParameters.PageSize, gender = personsResourceParameters.Gender, searchQuery = personsResourceParameters.SearchQuery })); case ResourceUriType.Current: default: return(Url.Link("GetPersons", new { fields = personsResourceParameters.Fields, orderBy = personsResourceParameters.OrderBy, pageNumber = personsResourceParameters.PageNumber, pageSize = personsResourceParameters.PageSize, gender = personsResourceParameters.Gender, searchQuery = personsResourceParameters.SearchQuery })); } }
public IActionResult GetPersons([FromQuery] PersonsResourceParameters personsResourceParameters) { if (!_propertyMappingService.ValidMappingExistsFor <PersonDto, Person>(personsResourceParameters.OrderBy)) { return(BadRequest()); } if (!_propertyCheckerService.TypeHasProperties <PersonDto>(personsResourceParameters.Fields)) { return(BadRequest()); } var peopleFromRepo = _personRepository.GetPersons(personsResourceParameters); //var previousPageLink = peopleFromRepo.HasPrevious ? // CreatePersonsResourceUri(personsResourceParameters, ResourceUriType.PreviousPage) : null; //var nextPageLink = peopleFromRepo.HasNext ? // CreatePersonsResourceUri(personsResourceParameters, ResourceUriType.NextPage) : null; var paginationMetadata = new { totalCount = peopleFromRepo.TotalCount, pageSize = peopleFromRepo.PageSize, currentPage = peopleFromRepo.CurrentPage, totalPages = peopleFromRepo.TotalPages }; // O mapper serve para não ter que andar a fazer isto para todos //var people = new List<PersonDto>(); //foreach (var person in peopleFromRepo) //{ // people.Add(new PersonDto() // { // Id = person.Id, // Name = $"{person.FirstName} {person.LastName}", // Address = person.Address, // Age = person.DateOfBirth.GetCurrentAge(), // Contact = person.Contact, // Email = person.Email, // NIF = person.NIF, // Sex = person.Sex // }); //} Response.Headers.Add("X-Pagination", JsonSerializer.Serialize(paginationMetadata)); var links = CreateLinksForPersons(personsResourceParameters, peopleFromRepo.HasNext, peopleFromRepo.HasPrevious); var shapedPersons = _mapper.Map <IEnumerable <PersonDto> >(peopleFromRepo) .ShapeData(personsResourceParameters.Fields); var shapedPersonsWithLinks = shapedPersons.Select(person => { var personAsDictionary = person as IDictionary <string, object>; var personLinks = CreateLinksForPerson((Guid)personAsDictionary["Id"], null); personAsDictionary.Add("links", personLinks); return(personAsDictionary); }); var linkedCollectionResource = new { value = shapedPersonsWithLinks, links }; return(Ok(linkedCollectionResource)); }