将资源模型自动映射到 WebAPI 中的实体 - PUT 可为空

Posted

技术标签:

【中文标题】将资源模型自动映射到 WebAPI 中的实体 - PUT 可为空【英文标题】:Automapping Resource model to Entity in WebAPI - PUT nullable 【发布时间】:2021-03-24 12:46:14 【问题描述】:

我正在尝试使用我的 EFCore 实体类上的自动映射资源模型通过 WebAPI 修改数据。 我已经设法让 GET、GET(by id) 和 POST 使用这种方法正常工作。

现在我面临的问题是在尝试使用此资源执行 PUT 时收到 Automapper 可为空的类型对错误消息。

这是我的实体:

[Table("BlazorWebApiDemo")]
    public partial class BlazorEntity
    
        [Key]
        public int Id  get; set; 
        [Column("First Name")]
        [StringLength(50)]
        public string? FirstName  get; set; 
        [Column("Last Name")]
        [StringLength(50)]
        public string? LastName  get; set; 
        [StringLength(50)]
        public string? Address  get; set; 
     

这是我的资源模型:

    public class BlazorEntityModel
    
        [Key]
        public int Id  get; set; 
        [StringLength(50)]
        public string FirstName  get; set; 
        [StringLength(50)]
        public string LastName  get; set; 
        [StringLength(50)]
        public string Address  get; set; 
    

我的 Automapper 个人资料:

    public class BlazorEntityProfile : Profile
    
        public BlazorEntityProfile()
        
            this.CreateMap<BlazorEntity, BlazorEntityModel>()
                .ForMember(dest => dest.FirstName, opt => opt.NullSubstitute(""))
                .ForMember(dest => dest.LastName, opt => opt.NullSubstitute(""))
                .ForMember(dest => dest.Address, opt => opt.NullSubstitute(""));
        
    

注意:我已经为每个成员添加了 NullSubstitute,因为我认为这可以解决错误。没有。

还有我在 API 控制器中的 PUT 方法。

        [HttpPut("id:int")]
        public async Task<ActionResult<BlazorEntityModel>> UpdateBlazorItem(int id, BlazorEntityModel blazorEntityModel)
        
            try
            
                var updatedBlazorEntity = await blazorRepository.GetBlazorById(id);
                if (blazorEntityModel == null) return NotFound($"LetItem with the ID: id not found");

                mapper.Map(blazorEntityModel, updatedBlazorEntity);

                if(await blazorRepository.SaveChangesAsync())
                
                    return mapper.Map<BlazorEntityModel>(updatedBlazorEntity);
                

            
            catch (Exception e)
            
                return StatusCode(StatusCodes.Status500InternalServerError,
                                  e);
            

            return BadRequest();
        

注意: blazorRepository.GetBlazorById(id) 检索 BlazorEntity。

SaveChangesAsync

        public async Task<bool> SaveChangesAsync()
        
            return await(context.SaveChangesAsync()) > 0;
        

招摇测试:

错误信息:

有什么想法吗?

【问题讨论】:

我不确定这是否会导致错误,但您的操作属性可能应该是HttpPut("id:int")(而不是HttpPut("id:int"))。否则id:int 部分被视为 URL 的一部分,而不是指定替换参数 【参考方案1】:

您在 Mapper Profile 上的代码已反转,请尝试将 this.CreateMap&lt;BlazorEntity, BlazorEntityModel&gt;() 更改为 this.CreateMap&lt;BlazorEntityModel, BlazorEntity&gt;()

或者你可以使用.ReverseMap()来双向使用这个配置

this.CreateMap<BlazorEntity, BlazorEntityModel>()
    .ForMember(dest => dest.FirstName, opt => opt.NullSubstitute(""))
    .ForMember(dest => dest.LastName, opt => opt.NullSubstitute(""))
    .ForMember(dest => dest.Address, opt => opt.NullSubstitute(""))
    .ReverseMap();

注意:您不需要将string 指定为string?,因为string 已经是可空类型

【讨论】:

好的,这帮助我摆脱了可为空的类型对错误,但我仍然收到类似的错误“System.NotSupportedException:不支持“System.Type”实例的序列化和反序列化,应该支持避免,因为它们会导致安全问题。路径:$.TargetSite.DeclaringType.' 别在意我的最后评论。弄清楚上面的错误信息是什么。原来我不能在我的资源模型中使用 ID [Key] 字段。评论这个问题解决了这个问题。尽管杰斐逊会接受你的回答。谢谢! string already is a nullable type - 如果启用了nullable reference types,我认为这不一定是正确的

以上是关于将资源模型自动映射到 WebAPI 中的实体 - PUT 可为空的主要内容,如果未能解决你的问题,请参考以下文章

您如何将乐观并发与 WebAPI OData 控制器一起使用

VS2015 + SQL Server 反向生成实体模型

从实体框架映射到自定义域模型类?

如何将一个自定义实体映射到实体框架中的某些数据库表?

从日期时间类型将视图中的元素自动映射到模型

在使用协程时,我们如何将域模型映射到网络实体?