【问题标题】:Which approach to use for model binding a custom type用于模型绑定自定义类型的方法
【发布时间】:2021-09-17 19:05:45
【问题描述】:

我的 API 控制器有一个如下所示的端点:

public async Task<IActionResult> Update([FromBody] UpdateCommand command) { /* ... */ }

command 看起来像这样:

public class UpdateCommand {
  public string Username { get; set; }
  public Id Id { get; set; }               // <--- here's the problem
}

Id 是一个值对象,看起来像这样:

public class Id : SimpleValueObject<long> {
  // base class has: IComparable, equality, GetHashCode, etc.
  public Id(long value) : base(value) { }
  public Id(string value) : base(Parse(value)) { }
  private static long Parse(string value) { /* ... */ }
}

客户端会发送这个:

{
  "username": "foo",
  "id": 1
}

现在我希望模型绑定能够自动工作。但我很困惑如何做到这一点。

我实现了IModelBinderIModelBinderProvider,但这并没有帮助。然后我注意到了文档say this:

通常不应该用于将字符串转换为自定义类型,TypeConverter 通常是更好的选择。

所以我实现了TypeConverter,但这也没有帮助。

然后我想实现一个JsonConverter&lt;T&gt;,但是框架现在使用的不是Newtonsoft,所以我没有走多远。

所以我的问题是:我必须做些什么来促进自定义类型的自动绑定。我只需要知道该走哪条路,剩下的我会想办法。

(作为一个附带问题:请帮助我了解何时应该实现模型绑定器、类型转换器和 json 转换器。)

【问题讨论】:

  • “然后我想实现一个JsonConverter,但是现在框架使用了Newtonsoft以外的东西,所以我没有走多远。”是的,它是System.Text.Json,它也允许你写custom converters
  • @GuruStron 谢谢我刚刚发现 Newtonsoft 被 System.Text.Json 命名空间所取代。但是请告诉我,是我应该实现的JsonConverter&lt;long&gt;,还是其他什么?
  • 如果您想将某些内容反序列化为您的 Id 类型,则应该是 JsonConverter&lt;Id&gt;

标签: c# model-binding typeconverter asp.net-core-5.0 jsonconverter


【解决方案1】:

我仍然不明白何时使用自定义模型绑定器、自定义类型转换器和自定义 json 转换器。

但似乎这种情况的解决方案是自定义JsonConverter&lt;T&gt;

这对我有用:

public class IdConverter : JsonConverter<Id> {

  public override Id? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) {
    if (reader.TokenType is not JsonTokenType.String and not JsonTokenType.Number)
      throw new JsonException();
    try {
      if (reader.TokenType is JsonTokenType.String) {
        var value = reader.GetString();
        return new Id(value);
      }
      else {
        var value = reader.GetInt64();
        return new Id(value);
      }
    }
    catch {
      throw new JsonException();
    }
  }

  public override void Write(Utf8JsonWriter writer, Id value, JsonSerializerOptions options) =>
    writer.WriteNumberValue(value.Value);

}

【讨论】:

    猜你喜欢
    • 2011-02-08
    • 2019-12-07
    • 1970-01-01
    • 1970-01-01
    • 2017-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多