You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET Web API中AutoMapper未忽略可空布尔值问题排查

可空布尔类型在AutoMapper中未被忽略的问题解析

问题场景

基于.NET 6开发ASP.NET Web API的餐厅信息修改功能,核心实体Restaurant的HasDelivery是非可空布尔类型,请求DTOModifyRestaurantDto中对应属性为可空布尔类型。配置AutoMapper仅映射非null值后,字符串类型属性正常生效,但可空布尔值始终被转为false,未被忽略。

相关代码

Restaurant实体类

public class Restaurant
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string? Description { get; set; }
    public string Category { get; set; }
    public bool HasDelivery { get; set; }
    public string ContactEmail { get; set; }
    public string ContactNumber { get; set; }

    public int? CreatedById { get; set; }
    public virtual User CreatedBy { get; set; }

    public int AddressId { get; set; }
    public virtual Address Address { get; set; }

    public virtual List<Dish> Dishes { get; set; }
}

ModifyRestaurantDto类

public class ModifyRestaurantDto
{
    [MaxLength(25)]
    public string? Name { get; set; }

    [MaxLength(100)]
    public string? Description { get; set; }
    public bool? HasDelivery { get; set; }
}

UpdateAsync方法

public async Task UpdateAsync(int id, ModifyRestaurantDto modifyRestaurantDto)
{
    var restaurant = await _dbContext
        .Restaurants
        .FirstOrDefaultAsync(r => r.Id == id)
        ?? throw new NotFoundException("Restaurant not found...");

    var authorizationResult = _authorizationService
        .AuthorizeAsync(
            _userContextService.User,
            restaurant,
            new ResourceOperationRequirement(ResourceOperation.Update))
        .Result;

    if (!authorizationResult.Succeeded) 
        throw new ForbidException();

    _mapper.Map(modifyRestaurantDto, restaurant);
    await _dbContext.SaveChangesAsync();
}

AutoMapper配置

public class RestaurantMappingProfile : Profile
{
    public RestaurantMappingProfile()
    {
        CreateMap<ModifyRestaurantDto, Restaurant>()
            .ForAllMembers(opts => opts.Condition((src, dest, value) => value is not null));
    }
}

问题原因

问题出在AutoMapper的Condition参数逻辑上:当DTO中的HasDelivery为null时,AutoMapper会先将这个可空布尔值转换为目标属性(非可空bool)的默认值false,再把这个转换后的false传入Condition的value参数中。此时value is not null判断为true,所以会执行映射,将false覆盖到实体的HasDelivery属性上,导致原本的属性值被修改。

解决方案

方案一:全局修改判断逻辑,直接检查源属性值

修改AutoMapper配置,通过上下文获取源对象的原始属性值,避免转换后的默认值干扰:

public class RestaurantMappingProfile : Profile
{
    public RestaurantMappingProfile()
    {
        CreateMap<ModifyRestaurantDto, Restaurant>()
            .ForAllMembers(opts => opts.Condition((src, dest, _, context) => 
            {
                // 获取源对象当前属性的原始值
                var srcProperty = context.MemberMap.SourceMember;
                var srcValue = srcProperty.GetValue(src);
                return srcValue != null;
            }));
    }
}

方案二:单独针对可空布尔属性配置条件

如果只需要处理HasDelivery属性,可单独为其设置判断条件,其他属性保持原有逻辑:

public class RestaurantMappingProfile : Profile
{
    public RestaurantMappingProfile()
    {
        CreateMap<ModifyRestaurantDto, Restaurant>()
            // 仅当源属性有值时才映射HasDelivery
            .ForMember(dest => dest.HasDelivery, opt => 
                opt.Condition(src => src.HasDelivery.HasValue))
            // 其他属性保持原有非null判断
            .ForAllOtherMembers(opts => opts.Condition((src, dest, value) => value is not null));
    }
}

内容的提问来源于stack exchange,提问作者BartTux

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 03:10:40