千家信息网

如何使用AutoMapper实现GET请求

发表于:2025-11-10 作者:千家信息网编辑
千家信息网最后更新 2025年11月10日,这篇文章主要讲解了"如何使用AutoMapper实现GET请求",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"如何使用AutoMapper实现GET请求
千家信息网最后更新 2025年11月10日如何使用AutoMapper实现GET请求

这篇文章主要讲解了"如何使用AutoMapper实现GET请求",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"如何使用AutoMapper实现GET请求"吧!

    需求

    需求很简单:实现GET请求获取业务数据。在这个阶段我们经常使用的类库是AutoMapper。

    目标

    合理组织并使用AutoMapper,完成GET请求。

    原理与思路

    首先来简单地介绍一下这这个类库。

    关于AutoMapper

    在业务侧代码和数据库实体打交道的过程中,一个必不可少的部分就是返回的数据类型转换。对于不同的请求来说,希望得到的返回值是数据库实体的一部分/组合/计算等情形。我们就经常需要手写用于数据对象转换的代码,但是转换前后可能大部分情况下有着相同名称的字段或属性。这部分工作能避免手写冗长的代码吗?可以。

    我们希望接受的请求和返回的值(统一称为model)具有以下两点需要遵循的原则:

    1.每个model被且只被一个API消费;

    2.每个model里仅仅包含API发起方希望包含的必要字段或属性。

    AutoMapper库就是为了实现这个需求而存在的,它的具体用法请参考官方文档,尤其是关于Convention的部分,避免重复劳动。

    实现

    所有需要使用AutoMapper的地方都集中在Application项目中。

    引入AutoMapper

    $ dotnet add src/TodoList.Application/TodoList.Application.csproj package AutoMapper.Extensions.Microsoft.DependencyInjection

    然后在Application/Common/Mappings下添加配置,提供接口的原因是我们后面就可以在DTO里实现各自对应的Mapping规则,方便查找。

    IMapFrom.cs

    using AutoMapper;namespace TodoList.Application.Common.Mappings;public interface IMapFrom{    void Mapping(Profile profile) => profile.CreateMap(typeof(T), GetType());}

    MappingProfile.cs

    using System.Reflection;using AutoMapper;namespace TodoList.Application.Common.Mappings;public class MappingProfile : Profile{    public MappingProfile() => ApplyMappingsFromAssembly(Assembly.GetExecutingAssembly());    private void ApplyMappingsFromAssembly(Assembly assembly)    {        var types = assembly.GetExportedTypes()            .Where(t => t.GetInterfaces().Any(i =>                i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IMapFrom<>)))            .ToList();        foreach (var type in types)        {            var instance = Activator.CreateInstance(type);            var methodInfo = type.GetMethod("Mapping")                             ?? type.GetInterface("IMapFrom`1")!.GetMethod("Mapping");            methodInfo?.Invoke(instance, new object[] { this });        }    }}

    DependencyInjection.cs进行依赖注入:

    DependencyInjection.cs

    // 省略其他...services.AddAutoMapper(Assembly.GetExecutingAssembly());services.AddMediatR(Assembly.GetExecutingAssembly());return services;

    实现GET请求

    在本章中我们只实现TodoListQuery接口(GET),并且在结果中包含TodoItem集合,剩下的接口后面的文章中逐步涉及。

    GET All TodoLists

    Application/TodoLists/Queries/下新建一个目录GetTodos用于存放创建一个TodoList相关的所有逻辑:

    定义TodoListBriefDto对象:

    TodoListBriefDto.cs

    using TodoList.Application.Common.Mappings;namespace TodoList.Application.TodoLists.Queries.GetTodos;// 实现IMapFrom接口,因为此Dto不涉及特殊字段的Mapping规则// 并且属性名称与领域实体保持一致,根据Convention规则默认可以完成Mapping,不需要额外实现public class TodoListBriefDto : IMapFrom{    public Guid Id { get; set; }    public string? Title { get; set; }    public string? Colour { get; set; }}

    GetTodosQuery.cs

    using AutoMapper;using AutoMapper.QueryableExtensions;using MediatR;using Microsoft.EntityFrameworkCore;using TodoList.Application.Common.Interfaces;namespace TodoList.Application.TodoLists.Queries.GetTodos;public class GetTodosQuery : IRequest>{}public class GetTodosQueryHandler : IRequestHandler>{    private readonly IRepository _repository;    private readonly IMapper _mapper;    public GetTodosQueryHandler(IRepository repository, IMapper mapper)    {        _repository = repository;        _mapper = mapper;    }    public async Task> Handle(GetTodosQuery request, CancellationToken cancellationToken)    {        return await _repository            .GetAsQueryable()            .AsNoTracking()            .ProjectTo(_mapper.ConfigurationProvider)            .OrderBy(t => t.Title)            .ToListAsync(cancellationToken);    }}

    最后实现Controller层的逻辑:

    TodoListController.cs

    // 省略其他...[HttpGet]public async Task>> Get(){    return await _mediator.Send(new GetTodosQuery());}

    GET Single TodoList

    首先在Application/TodoItems/Queries/下新建目录GetTodoItems用于存放获取TodoItem相关的所有逻辑:

    定义TodoItemDtoTodoListDto对象:

    TodoItemDto.cs

    using AutoMapper;using TodoList.Application.Common.Mappings;using TodoList.Domain.Entities;namespace TodoList.Application.TodoItems.Queries.GetTodoItems;// 实现IMapFrom接口public class TodoItemDto : IMapFrom{    public Guid Id { get; set; }    public Guid ListId { get; set; }    public string? Title { get; set; }    public bool Done { get; set; }    public int Priority { get; set; }    // 实现接口定义的Mapping方法,并提供除了Convention之外的特殊字段的转换规则    public void Mapping(Profile profile)    {        profile.CreateMap()            .ForMember(d => d.Priority, opt => opt.MapFrom(s => (int)s.Priority));    }}

    TodoListDto.cs

    using TodoList.Application.Common.Mappings;using TodoList.Application.TodoItems.Queries.GetTodoItems;namespace TodoList.Application.TodoLists.Queries.GetSingleTodo;// 实现IMapFrom接口,因为此Dto不涉及特殊字段的Mapping规则// 并且属性名称与领域实体保持一致,根据Convention规则默认可以完成Mapping,不需要额外实现public class TodoListDto : IMapFrom{    public Guid Id { get; set; }    public string? Title { get; set; }    public string? Colour { get; set; }    public IList Items { get; set; } = new List();}

    创建一个根据ListId来获取包含TodoItems子项的spec:

    TodoListSpec.cs

    using Microsoft.EntityFrameworkCore;using TodoList.Application.Common;namespace TodoList.Application.TodoLists.Specs;public sealed class TodoListSpec : SpecificationBase{    public TodoListSpec(Guid id, bool includeItems = false) : base(t => t.Id == id)    {        if (includeItems)        {            AddInclude(t => t.Include(i => i.Items));        }    }}

    我们仍然为这个查询新建一个GetSingleTodo目录,并实现GetSIngleTodoQuery

    GetSingleTodoQuery.cs

    using AutoMapper;using AutoMapper.QueryableExtensions;using MediatR;using Microsoft.EntityFrameworkCore;using TodoList.Application.Common.Interfaces;using TodoList.Application.TodoLists.Specs;namespace TodoList.Application.TodoLists.Queries.GetSingleTodo;public class GetSingleTodoQuery : IRequest{    public Guid ListId { get; set; }}public class ExportTodosQueryHandler : IRequestHandler{    private readonly IRepository _repository;    private readonly IMapper _mapper;    public ExportTodosQueryHandler(IRepository repository, IMapper mapper)    {        _repository = repository;        _mapper = mapper;    }    public async Task Handle(GetSingleTodoQuery request, CancellationToken cancellationToken)    {        var spec = new TodoListSpec(request.ListId, true);        return await _repository            .GetAsQueryable(spec)            .AsNoTracking()            .ProjectTo(_mapper.ConfigurationProvider)            .FirstOrDefaultAsync(cancellationToken);    }}

    添加Controller逻辑,这里的Name是为了完成之前遗留的201返回的问题,后文会有使用。

    TodoListController.cs

    // 省略其他...[HttpGet("{id:Guid}", Name = "TodListById")]public async Task> GetSingleTodoList(Guid id){    return await _mediator.Send(new GetSingleTodoQuery    {        ListId = id    }) ?? throw new InvalidOperationException();}

    验证

    运行Api项目

    获取所有TodoList列表

    请求

    响应

    获取单个TodoList详情

    请求

    响应

    填一个POST文章里的坑

    在使用.NET 6开发TodoList应用(6)--使用MediatR实现POST请求中我们留了一个问题,即创建TodoList后的返回值当时我们是临时使用Id返回的,推荐的做法是下面这样:

    // 省略其他...[HttpPost]public async Task Create([FromBody] CreateTodoListCommand command){    var createdTodoList = await _mediator.Send(command);    // 创建成功返回201    return CreatedAtRoute("TodListById", new { id = createdTodoList.Id }, createdTodoList);}

    请求

    返回

    Content部分

    以及Header部分

    我们主要观察返回的HTTPStatusCode是201,并且在Header中location字段表明了创建资源的位置。

    感谢各位的阅读,以上就是"如何使用AutoMapper实现GET请求"的内容了,经过本文的学习后,相信大家对如何使用AutoMapper实现GET请求这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是,小编将为大家推送更多相关知识点的文章,欢迎关注!

    接口 字段 规则 数据 实体 属性 逻辑 部分 特殊 代码 名称 对象 就是 文章 目录 问题 需求 学习 一致 业务 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 远程桌面服务器协议 教育局网络安全自查情况报告 更换服务器内存显示错误 智慧政务网络安全 诗菲网络技术有限公司 中国联通公司邮箱服务器设置 苏州禾清通讯网络技术有限公司 飞翔网络安全 信息技术与网络安全方面 咸宁靠谱的软件开发中心 软件开发申请发明专利 沈阳东塔网络安全特训营培训机构 数据库快捷键是什么 国防科工局 网络安全 笔记本安全中心服务器 与医学有关的国际学术数据库 微信第三方的数据库 新的sql怎么建立数据库 数据库的自定义类型 2019网络安全上海广富林 思科服务器里面最厉害的是谁 海南高宇网络技术有限公司梦想花园能赚钱吗 网络技术编程 不属于关系数据库术语的是 思方科技互联网家电服务平台 微信第三方的数据库 医疗器械软件开发公司排名 查重学校的数据库 软件开发企业含义 王牌战争如何开创一个服务器
    0