使用ASP.NET Core 3.x 構建 RESTful API P11 P12 ActionResult of T 以及 AutoMapper
博客園文章Id:12665843
IActionResult
實際上針對IActionResult接口有一個實現類,ActionResult<T> 所以一般當我們知道明確的返回類型時,我們也應該明確定義Action方法的返回值類型,示例代碼如下:
/// <summary>
/// 獲取所有公司信息
/// </summary>
[HttpGet]
//public async Task<IActionResult> GetCompanies()
public async Task<ActionResult<IEnumerable<CompanyDto>>> GetCompanies()
{
var companies = await this._companyRepository.GetCompaniesAsync();
if (companies == null)
{
return NotFound(); // 404 NotFound
}
//return Ok(companies);
var companyDtos = new List<CompanyDto>();
foreach (var item in companies)
{
companyDtos.Add(new CompanyDto
{
Id = item.Id,
Name = item.Name
});
}
return Ok(companyDtos);
}
這樣做的好處是,我們可以將返回的資源,具體的類型明確化,它的好處體現在,比如當我們使用Swagger插件來生成接口文檔時,就可以明確的知道返回值類型了.
以上面代碼爲例,接口方法返回的結果類型實際上可以有以下幾種形式:
-
當申明的返回值類型爲:
Task<ActionResult<IEnumerable<CompanyDto>>>
那麼返回值類型可以寫成return companyDtos
,也可以寫成return Ok(companyDtos)
; -
當聲明的返回值類型爲: 在Task中直接是返回值類型 如:
Task<IEnumerable<CompanyDto>>
那麼返回值類型就應該返回具體的類型return companyDtos
; -
當聲明的返回值類型爲: 在Task中的類型爲
IActionResult
那麼具體的返回值,可以寫成return Ok(companyDtos)
這種形式.
綜上所述,我們應該儘可能的使用第一種寫法.
對象映射器 AutoMapper
在 .Net 的生態中,AutoMapper 是比較豐富的對象映射器,它提供了豐富的配置方法,方便開發者對兩個對象之間配置映射關係.
- 首先我們需要先通過Nuget來安裝AutoMapper的依賴項.
AutoMapper.Extensions.Microsoft.DependencyInjection可以更好的和 .Net Core的管道進行結合.
A convention-based object-object mapper
基於約定的對象到對象的映射器
- 然後我們需要在 .Net Core容器配置的方法中,註冊AutoMapper服務.
/*
* 在容器配置方法中,添加AutoMapper服務,
* 參數的意義上,在指定程序集中掃描 AutoMapper 的配置文件.
*/
services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());
- 在項目下添加Profiles文件夾,此文件夾中用於裝載AutoMapper映射關係的配置.
配置代碼:
using AutoMapper;
using Routine.Api.Entitle;
using Routine.Api.Models;
namespace Routine.Api.Profiles
{
public class CompanyProfile : Profile
{
/// <summary>
/// 需要在構造函數中配置映射關係
/// </summary>
public CompanyProfile()
{
/*
* 創建從Company(原對象),到CompanyDto(目標對象)的映射
*/
CreateMap<Company, CompanyDto>()
.ForMember(
dest=>dest.CompanyName,//目標屬性
opt=>opt.MapFrom(src=>src.Name) //表示配置目標屬性的映射源 即從Company中的name映射到CompanyDto中的CompanyName
);
}
}
}
AutoMapper的一些要點:
- AutoMapper是基於約定的,如果原對象,和目標對象中的屬性名稱是相同的,那麼AutoMapper會自動進行映射.
- 如果目標類型的某個屬性在源類型中沒有,那麼就會自動會被忽略,不會被賦值,即爲null.
- 針對自動映射沒有辦法成功的屬性,AutoMapper會提供一系列可以配置的方法,用於指定屬性間的映射關係.
- 使用AutoMapper 來組織映射,如果要使用AutoMapper來組織映射,我們需要在控制器的構造函數中,配置注入.
private readonly ICompanyRepository _companyRepository;
private readonly IMapper _mapper;
public CompaniesController(ICompanyRepository companyRepository,IMapper mapper)
{
_companyRepository = companyRepository ?? throw new ArgumentNullException(nameof(companyRepository));
_mapper = mapper ?? throw new ArgumentNullException(nameof(mapper));
}
- 使用AutoMapper的代碼如下:
/// <summary>
/// 獲取所有公司信息
/// </summary>
[HttpGet]
//public async Task<IActionResult> GetCompanies()
public async Task<ActionResult<IEnumerable<CompanyDto>>> GetCompanies()
{
var companies = await this._companyRepository.GetCompaniesAsync();
if (companies == null)
{
return NotFound(); // 404 NotFound
}
//return Ok(companies);
//自己指定映射關係
//var companyDtos = new List<CompanyDto>();
//foreach (var item in companies)
//{
// companyDtos.Add(new CompanyDto
// {
// Id = item.Id,
// CompanyName = item.Name
// });
//}
//return Ok(companyDtos);
//使用AutoMapper的映射關係
//T是目標類型, 參數中是源類型
var result = this._mapper.Map<IEnumerable<CompanyDto>>(companies);
return Ok(result);
}
- 以上文檔參考自:
IActionResult
AutoMapper