/// <summary>
        /// 为集合资源添加HATEOAS的LINKS
        /// </summary>
        /// <param name="postResourceParameters"></param>
        /// <param name="hasPrevious">是否具有前一页属性</param>
        /// <param name="hasNext">是否具有后一页属性</param>
        /// <returns>LinkResource集合</returns>
        private IEnumerable <LinkResource> CreateLinksForPosts(PostQueryParameters postResourceParameters,
                                                               bool hasPrevious, bool hasNext)
        {
            var links = new List <LinkResource>
            {
                new LinkResource(
                    CreatePostUri(postResourceParameters, PaginationResourceUriType.CurrentPage, "getPosts"),
                    "self", "GET")
            };

            if (hasPrevious)
            {
                links.Add(
                    new LinkResource(
                        CreatePostUri(postResourceParameters, PaginationResourceUriType.PreviousPage, "getPosts"),
                        "previous_page", "GET"));
            }

            if (hasNext)
            {
                links.Add(
                    new LinkResource(
                        CreatePostUri(postResourceParameters, PaginationResourceUriType.NextPage, "getPosts"),
                        "next_page", "GET"));
            }

            return(links);
        }
        /// <summary>
        /// 生成前一页,后一页,当前页的URI链接方法
        /// </summary>
        /// <param name="parameters">页面的元数据</param>
        /// <param name="uriType">URI类型</param>
        /// <param name="actionName">需要调用的ActionName</param>
        /// <returns></returns>
        private string CreatePostUri(PostQueryParameters parameters, PaginationResourceUriType uriType, string actionName)
        {
            switch (uriType)
            {
            case PaginationResourceUriType.PreviousPage:
                var previousParameters = new
                {
                    pageIndex = parameters.PageIndex - 1,
                    pageSize  = parameters.PageSize,
                    orderBy   = parameters.OrderBy,
                    fields    = parameters.Fields
                };
                return(urlHelper.Link(actionName, previousParameters));

            case PaginationResourceUriType.NextPage:
                var nextParameters = new
                {
                    pageIndex = parameters.PageIndex + 1,
                    pageSize  = parameters.PageSize,
                    orderBy   = parameters.OrderBy,
                    fields    = parameters.Fields
                };
                return(urlHelper.Link(actionName, nextParameters));

            default:
                var currentParameters = new
                {
                    pageIndex = parameters.PageIndex,
                    pageSize  = parameters.PageSize,
                    orderBy   = parameters.OrderBy,
                    fields    = parameters.Fields
                };
                return(urlHelper.Link(actionName, currentParameters));
            }
        }
        public async Task <IActionResult> Get(PostQueryParameters postQueryParameters)
        {
            #region 参数合法性判断
            //排序字段合法性判断
            if (!string.IsNullOrWhiteSpace(postQueryParameters.OrderBy) &&
                !propertyMappingContainer.ValidateMappingExistsFor <PostResource, Post>(postQueryParameters.OrderBy))
            {
                return(BadRequest("排序属性映射关系不存在,或不可通过该排序属性排序"));
            }
            //塑形字段合法性判断
            if (!string.IsNullOrWhiteSpace(postQueryParameters.Fields) &&
                !typeHelperService.TypeHasProperties <PostResource>(postQueryParameters.Fields))
            {
                return(BadRequest("传入的塑形属性不合法"));
            }
            #endregion

            //返回带有元数据的PaginatedList数据
            var postsWithMateData = await postRepository.GetAllPostsAsync(postQueryParameters);

            //将posts集合映射为PostResource集合,取出其中的post数据集合
            var postResources = mapper.Map <IEnumerable <Post>, IEnumerable <PostResource> >(postsWithMateData);
            //针对ResourceModel进行属性塑形
            var shapedPostResources = postResources.ToDynamicIEnumerable(postQueryParameters.Fields);

            var previousPageLink = postsWithMateData.HasPrevious ? CreatePostUri(postQueryParameters, PaginationResourceUriType.PreviousPage, "GetPosts") : null;
            var nextPageLink     = postsWithMateData.HasNext ? CreatePostUri(postQueryParameters, PaginationResourceUriType.NextPage, "GetPosts") : null;
            #region 提取元数据,并将该数据添加到响应Response自定义X-Pagination的Header中
            //提取元数据
            var mate = new
            {
                postsWithMateData.PageSize,
                postsWithMateData.PageIndex,
                postsWithMateData.TotalItemsCount,
                postsWithMateData.PageCount,
                previousPageLink,
                nextPageLink
            };


            //将翻页元数据添加到响应Header的X-Pagination中
            Response.Headers.Add("X-Pagination", JsonConvert.SerializeObject(mate, new JsonSerializerSettings
            {
                ContractResolver = new CamelCasePropertyNamesContractResolver() //将所有mate元数据属性首字母小写返回
            }));
            #endregion

            //logger.LogError("测试的错误日志记录");
            //throw new Exception("发生了错误");
            return(Ok(shapedPostResources));
        }
        public async Task <PaginatedList <Post> > GetAllPostsAsync(PostQueryParameters postQueryParameters)
        {
            var query = myContext.Posts.AsQueryable();

            #region 根据需求 过滤相关字段
            if (!string.IsNullOrEmpty(postQueryParameters.Title))
            {
                var title = postQueryParameters.Title.Trim().ToLowerInvariant();
                //直接检索
                //query = query.Where(x => x.Title.ToLowerInvariant() == title);
                //模糊查询
                query = query.Where(x => x.Title.ToLowerInvariant().Contains(title));

                //将pageindex设置为第一页起始,防止出现检索的数据不显示的问题
                //需要考虑一下怎么解决
                //postQueryParameters.PageIndex = 0;
            }
            #endregion

            //query = query.OrderBy(x => x.id);

            //传入参数,实现属性排序,传入需要排序ResourceModel的属性
            query = query.ApplySort(postQueryParameters.OrderBy, propertyMappingContainer.Resolve <PostResource, Post>());


            var count = await query.CountAsync();



            var data = await query
                       .Skip(postQueryParameters.PageIndex *postQueryParameters.PageSize)
                       .Take(postQueryParameters.PageSize)
                       .ToListAsync();

            var paginatedList = new PaginatedList <Post>(postQueryParameters.PageIndex, postQueryParameters.PageSize, count, data);


            return(paginatedList);

            //return await myContext.Posts.ToListAsync();
        }
        public async Task <IActionResult> GetPostsHateoas(PostQueryParameters postQueryParameters)
        {
            #region 参数合法性判断
            //排序字段合法性判断
            if (!string.IsNullOrWhiteSpace(postQueryParameters.OrderBy) &&
                !propertyMappingContainer.ValidateMappingExistsFor <PostResource, Post>(postQueryParameters.OrderBy))
            {
                return(BadRequest("排序属性映射关系不存在,或不可通过该排序属性排序"));
            }
            //塑形字段合法性判断
            if (!string.IsNullOrWhiteSpace(postQueryParameters.Fields) &&
                !typeHelperService.TypeHasProperties <PostResource>(postQueryParameters.Fields))
            {
                return(BadRequest("传入的塑形属性不合法"));
            }
            #endregion

            //返回带有元数据的PaginatedList数据
            var postsWithMateData = await postRepository.GetAllPostsAsync(postQueryParameters);

            //将posts集合映射为PostResource集合,取出其中的post数据集合
            var postResources = mapper.Map <IEnumerable <Post>, IEnumerable <PostResource> >(postsWithMateData);
            //针对ResourceModel进行属性塑形
            var shapedPostResources = postResources.ToDynamicIEnumerable(postQueryParameters.Fields);

            #region 针对每个postResource添加HATEOAS的LINKS属性
            var shapedWithLinks = shapedPostResources.Select(x =>
            {
                var dict      = x as IDictionary <string, object>;
                var postLinks = CreateLinksForPost((int)dict["id"], postQueryParameters.Fields);
                dict.Add("links", postLinks);
                return(dict);
            });
            #endregion

            #region 针对整个postsResource添加HATEOAS的Links属性
            var links = CreateLinksForPosts(postQueryParameters, postsWithMateData.HasPrevious, postsWithMateData.HasNext);

            var result = new
            {
                values = shapedWithLinks,
                links
            };
            #endregion


            #region 提取元数据,并将该数据添加到响应Response自定义X-Pagination的Header中
            //提取元数据
            var mate = new
            {
                postsWithMateData.PageSize,
                postsWithMateData.PageIndex,
                postsWithMateData.TotalItemsCount,
                postsWithMateData.PageCount
            };


            //将翻页元数据添加到响应Header的X-Pagination中
            Response.Headers.Add("X-Pagination", JsonConvert.SerializeObject(mate, new JsonSerializerSettings
            {
                ContractResolver = new CamelCasePropertyNamesContractResolver() //将所有mate元数据属性首字母小写返回
            }));
            #endregion

            //logger.LogError("测试的错误日志记录");
            //throw new Exception("发生了错误");
            return(Ok(result));
        }