ASP|ASP .NET Core Web API_10_资源塑形

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

  1. IEnumerableExtensions
//集合资源塑性 public static class IEnumerableExtensions { public static IEnumerable ToDynamicIEnumerable(this IEnumerable source,string fields = null) { if (source ==null) { throw new ArgumentNullException(nameof(source)); } var expandoObjectList = new List(); var propertyInfoList = new List(); 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 = https://www.it610.com/article/propertyInfo.GetValue(sourceObject); ((IDictionary)dataShapedObject).Add(propertyInfo.Name, propertyValue); } expandoObjectList.Add(dataShapedObject); } return expandoObjectList; } }

  1. ObjectExtensions
//单个资源塑性 public static class ObjectExtensions { public static ExpandoObject ToDynamic(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 = https://www.it610.com/article/propertyInfo.GetValue(source); ((IDictionary)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 = https://www.it610.com/article/propertyInfo.GetValue(source); ((IDictionary)dataShapedObject).Add(propertyInfo.Name, propertyValue); } return dataShapedObject; } }

  1. 修改controller
[HttpGet(Name ="GetPosts")] public async Task Get(PostParameters postParameters) { var postList = await _postRepository.GetAllPostsAsync(postParameters); var postResources = _mapper.Map(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 Get(int id, string fields = null) { var post = await _postRepository.GetPostByIdAsync(id); if (post == null) { return NotFound(); //404 } var postResource = _mapper.Map(post); //单个资源塑性 var shapedPostResource = postResource.ToDynamic(fields); return Ok(shapedPostResource); //200 }

ASP|ASP .NET Core Web API_10_资源塑形
文章图片
集合资源
ASP|ASP .NET Core Web API_10_资源塑形
文章图片
单个资源
  1. 修改startup,返回资源命名为驼峰命名
services.AddMvc( options=> { options.ReturnHttpNotAcceptable = true; //开启406 options.OutputFormatters.Add(new XmlDataContractSerializerOutputFormatter()); }) .AddJsonOptions(options=> { options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); });

ASP|ASP .NET Core Web API_10_资源塑形
文章图片
驼峰命名资源名称 异常处理
  1. ITypeHelperService
public interface ITypeHelperService { bool TypeHasProperties(string fields); }

  1. TypeHelperService
public class TypeHelperService:ITypeHelperService { public bool TypeHasProperties(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();

  1. 修改Controller
[HttpGet(Name ="GetPosts")] public async Task Get(PostParameters postParameters) { if (!_propertyMappingContainer.ValidateMappingExistsFor(postParameters.OrderBy)) { return BadRequest("cannot finds fields for sorting."); } if (!_typeHelperService.TypeHasProperties(postParameters.Fields)) { return BadRequest("Fields not exist."); } var postList = await _postRepository.GetAllPostsAsync(postParameters); var postResources = _mapper.Map(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 Get(int id, string fields = null) { if (!_typeHelperService.TypeHasProperties(fields)) { return BadRequest("Fields not exist."); } var post = await _postRepository.GetPostByIdAsync(id); if (post == null) { return NotFound(); //404 } var postResource = _mapper.Map(post); //单个资源塑性 var shapedPostResource = postResource.ToDynamic(fields); return Ok(shapedPostResource); //200 }

ASP|ASP .NET Core Web API_10_资源塑形
文章图片
异常处理

    推荐阅读