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

文章图片
集合资源

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

文章图片
驼峰命名资源名称 异常处理
- ITypeHelperService
public interface ITypeHelperService
{
bool TypeHasProperties(string fields);
}
- 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;
}
}
- 注册TypeHelperService
services.AddTransient();
- 修改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
}

文章图片
异常处理
推荐阅读
- 关于Core|关于Core Image
- ASP.NET|ASP.NET Core应用开发思维导图
- 运行报错Cannot|运行报错Cannot find module '@babel/compat-data/corejs3-shipped-proposals’
- java|微软认真聆听了开源 .NET 开发社区的炮轰( 通过CLI 支持 Hot Reload 功能)
- 基于NET|基于NET Core 的Nuget包制作、发布和运用流程解析(完整过程)
- 3.UIkit|3.UIkit CoreFoundatin Foundation
- asp.net|asp.net core中使用log4net
- Asp.net|System.Globalization.DateTimeFormatInfo.InvariantInfo
- linux采用core的调试方法
- 奢侈品3