如何配置控制器以返回null而不是Guid.Empty?

4
为了让开发ASP.Net Core 2.2 API前端的开发人员更加轻松,我希望他们接收到“null”值而不是Guid.Empty值(在.net core中定义为“00000000-0000-0000-0000-000000000000”)。
通过创建以下数据传输对象,实现这种行为并不复杂:
public class ExampleDto
{
    public Guid? Id { get; set; }
}

然后像这样进行映射

public static void MapExampleEntity(this AutoMapperProfile profile)
{
    profile.CreateMap<ExampleEntity, ExampleDto>()
    .ForMember(dto => dto.Id, o => o.MapFrom(e => e.Id == Guid.Empty ? null : e.Id);
}

然而,对于我认为控制器应该能够通过某些配置处理的任务而言,这是大量的代码重复。是否有可能默认实现这种行为?

编辑以进一步说明我的问题(我收到了几个可行的解决方案,但我觉得它们都不是完全干净的方法来实现我想要做的事情):

我知道一般的方法是将其保留为空值,这也是我不想在代码中使用空值的原因。我希望保持我的数据传输对象(DTOs)形式如下:

public class ExampleDto
{
    public Guid Id { get; set; }
}

请使用以下表单:

public class ExampleDto
{
    public Guid? Id { get; set; }
}

为了避免无限的HasValue()检查。然而,我认为更具信息性和一致性的做法是返回这个(参见customerId):
{
"Id": "b3431f4d-ef87-4fb5-83e0-995a9e7c9f6a",
"Name": "A001",
"Description": null,
"Currency": null,
"CustomerId": null,
"Customer": null,
"CountryIso": 2
}

比这更好:
{
"Id": "b3431f4d-ef87-4fb5-83e0-995a9e7c9f6a",
"Name": "A001",
"Description": null,
"Currency": null,
"CustomerId": "00000000-0000-0000-0000-000000000000",
"Customer": null,
"CountryIso": 2
}

这是当前的行为。 这就是为什么我希望让Guid.Empty => null映射由控制器执行而不是AutoMapper(如果可能的话)。


我没有看到任何重复。重复在哪里?你能展示更多的代码来展示重复吗? - Sweeper
1
抱歉误解了,重复的原因在于我需要使用Guid配置每个dto(而且这是很多dtos)。 - Karel Křesťan
通常情况下,越来越少返回空对象(例如请参阅C# 8)。这是有充分理由的 - 在这个论坛上,“这是什么空引用异常”这个问题出现了多少次? - iakobski
http://docs.automapper.org/en/latest/Custom-type-converters.html - Lucian Bargaoanu
3个回答

3

好的,不知道为什么在询问之前我没有找到这个解决方案,但我觉得把它写在这里(因为我已经提出了问题)是合适的,供未来可能遇到同样问题的开发人员参考。

确实可以格式化控制器输出,而无需手动检查每个Dto中的值或添加AutoMapper行到其映射配置中!

首先创建一个类,该类派生自JsonConverted,如下所示:

   public class NullGuidJsonConverter : JsonConverter<Guid>
   {
      public override void WriteJson(JsonWriter writer, Guid value, JsonSerializer serializer)
      {
         writer.WriteValue(value == Guid.Empty ? null : value.ToString());
      }

      public override Guid ReadJson(JsonReader reader, Type objectType, Guid existingValue, bool hasExistingValue, JsonSerializer serializer)
      {
         var value = reader.Value.ToString();
         return reader.Value == null ? Guid.Empty : Guid.Parse(value);
      }
   }

然后在 Startup.cs 中的 Mvc 设置中添加此类。

services.AddMvc()
        .AddJsonOptions(options =>
            options.SerializerSettings.Converters.Insert(0, new NullGuidJsonConverter()))
        .SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

就是这样!Controller现在可以将Guid.Empty值转换为null了!


实际上,执行相同操作的AM类型转换器甚至更简单 :) - Lucian Bargaoanu

0

你已经知道Guid是一个值类型。如果你想发送null而不是空Guid,你可以检查ActualCustomerId == Guid.IsEmpty,如果为真,则将CustomerId设置为null。否则,就像你说的那样,可空类型是一种方法。如果这不是你想要的,我很抱歉。这意味着你需要检查Guid是否为空,如果为空,则将null设置为CustomerId。


是的,我知道这个解决方案,但我不想每次都手动检查。听起来像是你不想在有很多数据传输对象的代码库中出现的东西 :( - Karel Křesťan

0

尝试使用:

public class ExampleDto
{
    public Guid? Id { get{ return Id == Guid.Empty ? null : Id; } set; }
}

这确实是一个可行的解决方案,但它只是将代码重复从AutoMapper移动到DtoClasses(需要在每个Dto中指定Guid getter)。 - Karel Křesťan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接