将 null 映射到可空浮点数在 Automapper 中不起作用

huangapple go评论69阅读模式
英文:

mapping null to nulable float does not work in Automapper

问题

在这个情况下,你希望在使用AutoMapper映射时避免将源中的null值映射到目标中。问题出在 AutoMapper 会尝试将null值映射为目标类型的非空值,这就是为什么你看到异常的原因。

为了解决这个问题,你可以在AutoMapper配置中添加一个条件,只有在源成员不为null时才进行映射。在你的AutoMapperModelOne 类中,你可以修改 .Condition 方法的逻辑,如下所示:

opt.Condition((src, des, srcMember) =>
{
    // 只有当源成员不为null时才进行映射
    return srcMember != null;
});

通过这个更改,AutoMapper将仅在源成员不为null时才尝试进行映射,从而避免了将null映射到非空属性的问题。

请尝试这个修改,看看是否解决了你的问题。

英文:

I have this model:

namespace WebApplication1Sample.Models
{
    public class ModelOne
    {
        public int Id { get; set; }
        public float? Prop1 { get; set; }
        public float? Prop2 { get; set; }
    }
}

with this AutoMapper:

using WebApplication1Sample.Models;
using AutoMapper;
using Newtonsoft.Json.Linq;
using System.Reflection;

namespace App.Mappings
{
    public class AutoMapperModelOne : Profile
    {
        public AutoMapperModelOne()
        {
            CreateMap<JToken, ModelOne>()
            .ForAllMembers(opt =>
            {
                MemberInfo propDestination = opt.DestinationMember;
                string propName = propDestination.Name;

                opt.MapFrom(src => src.SelectToken(propName));

                opt.Condition((src, des, srcMember) =>
                {
                    if (srcMember == null)
                    {
                        return false;
                    }

                    //map all
                    return true;
                });
            });
        }
    }
}

In the automapper, I check if the srcMember is null, if it is I don't map it.

which I call with this:

[HttpPost]
[Route("mo")]
public void ModelOneMap()
{
    JToken tokenSample = new JObject();
    tokenSample["Id"] = 1232323;
    tokenSample["Prop1"] = 1;
    tokenSample["Prop2"] = null;

    ModelOne app =  _mapper.Map<ModelOne>(tokenSample);
    Console.WriteLine(app.Id);
}

As you can see, Prop2 is nullable. But when I try to pass null into it, it throws an exception:

AutoMapper.AutoMapperMappingException: Error mapping types.

Mapping types:
JToken -> ModelOne
Newtonsoft.Json.Linq.JToken -> WebApplication1Sample.Models.ModelOne

Type Map configuration:
JToken -> ModelOne
Newtonsoft.Json.Linq.JToken -> WebApplication1Sample.Models.ModelOne

Destination Member:
Prop2

 ---> System.ArgumentException: Can not convert Null to Single.
   at Newtonsoft.Json.Linq.JToken.op_Explicit(JToken value)
   at lambda_method4(Closure , Object , ModelOne , ResolutionContext )
   --- End of inner exception stack trace ---
   at lambda_method4(Closure , Object , ModelOne , ResolutionContext )
   at WebApplication1Sample.Controllers.WeatherForecastController.ModelOneMap() in C:\Users\prosy.arceno\Desktop\C sharp\WebApplication1Sample\WebApplication1Sample\Controllers\WeatherForecastController.cs:line 35
   at Microsoft.Extensions.Internal.ObjectMethodExecutor.<>c__DisplayClass33_0.<WrapVoidMethod>b__0(Object target, Object[] parameters)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.VoidResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeActionMethodAsync()
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeNextActionFilterAsync()
--- End of stack trace from previous location ---
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync()
--- End of stack trace from previous location ---
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|20_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
   at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
   at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
   at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext)
   at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

I don't understand why it's behaving this way since my destination property is nullable float.

How do I achieve the result that I want where I refrain from mapping all null values from source into the destination?

答案1

得分: 1

你可以尝试使用前置条件检查,例如:

var nullable = opt.DestinationMember.GetMemberType().IsNullableType();
opt.PreCondition((src, context) =>
{
    if (nullable && src.SelectToken(opt.DestinationMember.Name).Type == JTokenType.Null)
    {
        return false;
    }
    else
    {
        return true;
    }
});
英文:

You could try check with precondition like:

var nullable = opt.DestinationMember.GetMemberType().IsNullableType();
                opt.PreCondition((src,context) =>
                {
                    if (nullable&& src.SelectToken(opt.DestinationMember.Name).Type== JTokenType.Null)
                    {
                        return false;
                    }
                    else
                    {
    
                        return true;
                    }
    
                   
                });

huangapple
  • 本文由 发表于 2023年6月1日 13:37:28
  • 转载请务必保留本文链接:https://go.coder-hub.com/76378933.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定