您需要 3 个不同的状态来获取电子邮件值:
- 更新的填充值(例如
test@mail.com)
-
null 值是否应删除电子邮件
- 如果不应触摸电子邮件,则缺少值。
所以问题实际上是如何在模型的string 属性中表达这三种状态。您不能仅使用原始 string 属性来执行此操作,因为正如您正确描述的那样,null 值和缺失值会发生冲突。
解决方案是使用一些标志来指示请求中是否提供了该值。您可以将此标志作为模型中的另一个属性,也可以在string 上创建一个简单的包装器,非常类似于Nullable<T> 类。
我建议创建简单的通用OptionalValue<T> 类:
public class OptionalValue<T>
{
private T value;
public T Value
{
get => value;
set
{
HasValue = true;
this.value = value;
}
}
public bool HasValue { get; set; }
}
然后你需要自定义的JsonConverter,它可以将通常的json值反序列化为OptionalValue<T>:
class OptionalValueConverter<T> : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(OptionalValue<T>);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
return new OptionalValue<T>
{
Value = (T) reader.Value,
};
}
public override bool CanWrite => false;
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
您的模型将如下所示:
public class SomeModel
{
public string Surname { get; set; }
[JsonConverter(typeof(OptionalValueConverter<string>))]
public OptionalValue<string> Email { get; set; } = new OptionalValue<string>();
}
请注意,您为电子邮件分配了空的OptionalValue<string>()。如果输入 json 不包含 email 值而不是 Email 属性将保留它 OptionalValue 并将 HasValue 设置为 false。
如果输入json包含一些email,甚至null,那么OptionalValueConverter将创建OptionalValue的实例,HasValue设置为true。
现在在控制器操作中,您可以确定 email 的 3 种状态中的任何一种:
[HttpPatch]
public void Patch([FromBody]SomeModel data)
{
if (data.Email.HasValue)
{
// Email presents in Json
if (data.Email.Value == null)
{
// Email should be removed
}
else
{
// Email should be updated
}
}
else
{
// Email does not present in Json and should not be affected
}
}