ASP .NET Core Web API_10_资源塑形

资源塑形

如果资源的属性较多, 而且API消费者只需要一分部属性, 那么就应该考虑资源塑形
集合资源 单个资源 异常处理

  1. IEnumerableExtensions
//集合资源塑性
    public static class IEnumerableExtensions
    {
        public static IEnumerable<ExpandoObject> ToDynamicIEnumerable<TSource>(this IEnumerable<TSource> source,string fields = null)
        {
            if (source ==null)
            {
                throw new ArgumentNullException(nameof(source));
            }
            var expandoObjectList = new List<ExpandoObject>();
            var propertyInfoList = new List<PropertyInfo>();
            if (string.IsNullOrWhiteSpace(fields))
            {
                var propertyInfos = typeof(TSource).GetProperties(BindingFlags.Public | BindingFlags.Instance);
                propertyInfoList.AddRange(propertyInfos);
            }
            else
            {
                var fieldsAfterSplit = fields.Split(',').ToList();
                foreach (var field in fieldsAfterSplit)
                {
                    var propertyName = field.Trim();

                    if (string.IsNullOrEmpty(propertyName))
                    {
                        continue;
                    }

                    var propertyInfo = typeof(TSource).GetProperty(propertyName, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);
                    if (propertyInfo ==null)
                    {
                        throw new Exception($"Property {propertyName} was't found on {typeof(TSource)}");
                    }
                    propertyInfoList.Add(propertyInfo);
                }
            }

            foreach (TSource sourceObject in source)
            {
                var dataShapedObject = new ExpandoObject();
                foreach (var propertyInfo in propertyInfoList)
                {
                    var propertyValue = propertyInfo.GetValue(sourceObject);
                    ((IDictionary<string, object>)dataShapedObject).Add(propertyInfo.Name, propertyValue);
                }
                expandoObjectList.Add(dataShapedObject);
            }
            return expandoObjectList;
        }
    }
  1. ObjectExtensions
//单个资源塑性
    public static class ObjectExtensions
    {
        public static ExpandoObject ToDynamic<TSoucre>(this TSoucre source,string fields = null)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }
            var dataShapedObject = new ExpandoObject();
            if (string.IsNullOrWhiteSpace(fields))
            {
                var propertyInfos = typeof(TSoucre).GetProperties(BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);
                foreach (var propertyInfo in propertyInfos)
                {
                    var propertyValue = propertyInfo.GetValue(source);
                    ((IDictionary<string, object>)dataShapedObject).Add(propertyInfo.Name, propertyValue);
                }
                return dataShapedObject;
            }
            var fieldsAfterSplit = fields.Split(',').ToList();
            foreach (var field in fieldsAfterSplit)
            {
                var propertyName = field.Trim();
                var propertyInfo = typeof(TSoucre).GetProperty(propertyName, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);
                if (propertyInfo ==null)
                {
                    throw new Exception($"Can't found property {typeof(TSoucre)} on {propertyName}");
                }
                var propertyValue = propertyInfo.GetValue(source);
                ((IDictionary<string, object>)dataShapedObject).Add(propertyInfo.Name, propertyValue);
            }
            return dataShapedObject;
        }
    }
  1. 修改controller
  [HttpGet(Name ="GetPosts")]
        public async Task<IActionResult> Get(PostParameters postParameters)
        {
            var postList = await _postRepository.GetAllPostsAsync(postParameters);
            var postResources = _mapper.Map<IEnumerable<Post>, IEnumerable<PostResource>>(postList);

            //集合资源塑性
            var shapedPostResources = postResources.ToDynamicIEnumerable(postParameters.Fields);


            var previousPageLink = postList.HasPrevious ? CreatePostUri(postParameters, PaginationResourceUriType.PreviousPage) : null;
            var nextPageLink = postList.HasNext ? CreatePostUri(postParameters, PaginationResourceUriType.NextPage) : null;
            var meta = new
            {
                postList.PageSize,
                postList.PageIndex,
                postList.TotalItemsCount,
                postList.PageCount,
                previousPageLink,
                nextPageLink
            };
            Response.Headers.Add("X-Pagination", JsonConvert.SerializeObject(meta, new JsonSerializerSettings
            {
                //使得命名符合驼峰命名法
                ContractResolver = new CamelCasePropertyNamesContractResolver()
            }));
            return Ok(shapedPostResources);
[HttpGet("{id}")] 
        public async Task<IActionResult> Get(int id, string fields = null)
        {
            var post = await _postRepository.GetPostByIdAsync(id);
            if (post == null)
            {
                return NotFound();//404
            }
            var postResource = _mapper.Map<Post, PostResource>(post);
            
            //单个资源塑性
            var shapedPostResource = postResource.ToDynamic(fields);

            return Ok(shapedPostResource); //200
        }
集合资源

单个资源
  1. 修改startup,返回资源命名为驼峰命名
 services.AddMvc(
 options=>
 {
      options.ReturnHttpNotAcceptable = true; //开启406
      options.OutputFormatters.Add(new XmlDataContractSerializerOutputFormatter());
})
.AddJsonOptions(options=>
  {
     options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
 });
驼峰命名资源名称

异常处理

  1. ITypeHelperService
 public interface ITypeHelperService
    {
        bool TypeHasProperties<T>(string fields);
    }
  1. TypeHelperService
public class TypeHelperService:ITypeHelperService
    {
        public bool TypeHasProperties<T>(string fields)
        {
            if (string.IsNullOrWhiteSpace(fields))
            {
                return true;
            }
            var fieldsAfterSplit = fields.Split(',');
            foreach (var field in fieldsAfterSplit)
            {
                var propertyName = field.Trim();
                if (string.IsNullOrEmpty(propertyName))
                {
                    continue;
                }
                var propertyInfo = typeof(T)
                    .GetProperty(propertyName, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);

                if (propertyInfo == null)
                {
                    return false;
                }
            }
            return true;
        }
    }
  1. 注册TypeHelperService
services.AddTransient<ITypeHelperService, TypeHelperService>();
  1. 修改Controller
  [HttpGet(Name ="GetPosts")]
        public async Task<IActionResult> Get(PostParameters postParameters)
        {
            if (!_propertyMappingContainer.ValidateMappingExistsFor<PostResource,Post>(postParameters.OrderBy))
            {
                return BadRequest("cannot finds fields for sorting.");
            }
            if (!_typeHelperService.TypeHasProperties<PostResource>(postParameters.Fields))
            {
                return BadRequest("Fields not exist.");
            }
            var postList = await _postRepository.GetAllPostsAsync(postParameters);
            var postResources = _mapper.Map<IEnumerable<Post>, IEnumerable<PostResource>>(postList);

            //集合资源塑性
            var shapedPostResources = postResources.ToDynamicIEnumerable(postParameters.Fields);


            var previousPageLink = postList.HasPrevious ? CreatePostUri(postParameters, PaginationResourceUriType.PreviousPage) : null;
            var nextPageLink = postList.HasNext ? CreatePostUri(postParameters, PaginationResourceUriType.NextPage) : null;
            var meta = new
            {
                postList.PageSize,
                postList.PageIndex,
                postList.TotalItemsCount,
                postList.PageCount,
                previousPageLink,
                nextPageLink
            };
            Response.Headers.Add("X-Pagination", JsonConvert.SerializeObject(meta, new JsonSerializerSettings
            {
                //使得命名符合驼峰命名法
                ContractResolver = new CamelCasePropertyNamesContractResolver()
            }));
            return Ok(shapedPostResources);
        }

        [HttpGet("{id}")] 
        public async Task<IActionResult> Get(int id, string fields = null)
        {
            if (!_typeHelperService.TypeHasProperties<PostResource>(fields))
            {
                return BadRequest("Fields not exist.");
            }
            var post = await _postRepository.GetPostByIdAsync(id);
            if (post == null)
            {
                return NotFound();//404
            }
            var postResource = _mapper.Map<Post, PostResource>(post);
            
            //单个资源塑性
            var shapedPostResource = postResource.ToDynamic(fields);

            return Ok(shapedPostResource); //200
        }
异常处理
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 135,083评论 19 139
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 173,925评论 25 709
  • 用两张图告诉你,为什么你的 App 会卡顿? - Android - 掘金 Cover 有什么料? 从这篇文章中你...
    hw1212阅读 13,079评论 2 59
  • 01 又是下了一夜的雨,清晨出门看到人行道上铺满了银杏和梧桐的落叶。一叶知秋,几个月前,这些叶子都还骄傲地在树枝上...
    遇见小娜阅读 3,110评论 23 63
  • 一直向往大海,感觉海风很好,这一次,不枉此行,真的看到了电视剧中的大海,这次不失望。——致第一次海滩 海浪层层加剧...
    刘小盗阅读 648评论 3 1