美文网首页ASP .NET Core Web Api + Angular
ASP .NET Core Web API_10_资源塑形

ASP .NET Core Web API_10_资源塑形

作者: xtddw | 来源:发表于2018-10-22 20:44 被阅读30次

    资源塑形

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

    相关文章

      网友评论

        本文标题:ASP .NET Core Web API_10_资源塑形

        本文链接:https://www.haomeiwen.com/subject/inlnzftx.html