ASP .NET Core Web Api + Angular

ASP .NET Core Web API_10_资源塑形

2018-10-22  本文已影响30人  xtddw

资源塑形

如果资源的属性较多, 而且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
        }
异常处理
上一篇下一篇

猜你喜欢

热点阅读