3

我有一个 web api 控制器方法,它接受一个复合对象,其中一个属性是 DateTime。当我将对象作为 XML 发布时,一切正常。但是,如果我将其发布为 JSON,则会失败。

为了获得更多关于为什么它可能会失败的信息,我添加了一个自定义日期时间转换器,只需重用 Json.Net 附带的基本 IsoDateTimeConverter,并通过在转换后的值上放置一个断点,我可以看到值转换得很好,但是当它到达模型时,属性会填充一个新的日期时间,而不是我发送的值。发送与 XML 完全相同的模型可以正常工作。

我对事件的顺序以及它如何从转换为日期时间对象然后在模型绑定时立即丢失感到有些困惑。我在交互的两端使用 Json.Net IsoDateTimeConverter 进行序列化和反序列化。

JSON 设置:

NullValueHandling = NullValueHandling.Ignore,
DateFormatHandling = DateFormatHandling.IsoDateFormat,
DateTimeZoneHandling = DateTimeZoneHandling.Utc,
Converters = new JsonConverter[]
{
    new StringEnumConverter(),
    new IsoDateTimeConverter()
}

用于在 web api 端进行反序列化的自定义转换器(使用 IsoDateTimeConverter):

public class CustomDateTimeConverter : DateTimeConverterBase
{
    IsoDateTimeConverter isoConverter;

    public CustomDateTimeConverter()
    {
        isoConverter = new IsoDateTimeConverter();
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        isoConverter.WriteJson(writer, value, serializer);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var returned = isoConverter.ReadJson(reader, objectType, existingValue, serializer);
        return returned;
    }
}

模型上的日期属性(两端)

public DateTime DateOfBirth { get; set; }

正在发布的 Json 格式:

"DateOfBirth":"1980-02-01T00:00:00"

转换器价值:

{01/02/1980 00:00:00}

控制器中模型的值:

{01/01/0001 00:00:00}

断点时返回的变量显示正确的反序列化日期时间,但是之后的模型直接是新的日期时间。

相当困惑这如何反序列化并且决定它没有立即发生!非常感谢任何帮助。

在进一步调查中,似乎 json binder 通常也无法绑定属性 - 大量基本字符串属性未正确绑定,因此这可能是另一个问题的一部分。

4

3 回答 3

4

Json 不做日期。将它们作为字符串传回并在您的客户端脚本中解析它们。

http://www.hanselman.com/blog/OnTheNightmareThatIsJSONDatesPlusJSONNETAndASPNETWebAPI.aspx

于 2013-03-15T15:51:46.637 回答
0

事实证明,这与 JSON 无关 - JSON 正确反序列化,正如我通过覆盖日期转换器发现的那样。问题是对象上有必填字段,在 Web API 下也需要 [DataMember(IsRequired = true)] 才能强制执行必填字段。问题在于对象的其余部分没有用 [DataMember] 属性装饰,因此它们被忽略了——我假设模型被绑定时。

追踪令人讨厌的错误,特别是当解决方案如此简单时......

于 2013-03-18T10:36:26.890 回答
0
 function ConvertDateTime(dt) {
        var cdt = new Date();
        var dateString = dt.substr(6);
        var currentTime = new Date(parseInt(dateString));
        var month = currentTime.getMonth();
        var m = months[month];
        var day = currentTime.getDate();
        var year = currentTime.getFullYear();
        var hr = currentTime.getHours();
        var mi = currentTime.getMinutes();
        var date = day + "/" + m + "/" + year + " " + hr + ":" + mi;
        return date;
    }
于 2017-05-19T07:26:27.237 回答