【问题标题】:value changes when data is sent over Https通过 Https 发送数据时值发生变化
【发布时间】:2018-11-20 08:07:50
【问题描述】:

在 ASP.NET WebApi 中: 我有一个 DTO 课程:

public class DTO
{
    public string Date {get; set;}
}

当客户端(一个 Internet Explorer 插件)从这个 WebApi 请求数据时,我像这样返回 IEnumerable<DTO>

return Request.CreateResponse(System.Net.HttpStatusCode.OK, dtoObject)

其中dtoObject 的类型为IEnumerable<DTO>。 在调试时,我检查了dtoObject[0].Date 的值,它显示22-Nov-18 12:00:00 AM,这是预期值。

在 Internet Explorer 插件中: 我有一个名为 Model 的模型类:

public class Model
{
    public string Date {get; set;}
}

我这样请求 WebApi:

var response = await httpClient.PostAsJsonAsync(serviceUrl, requestDto);
var returnJson = await response.Content.ReadAsStringAsync();
var result = JsonConvert.DeserializeObject<IEnumerable<Model>>(returnJson)

现在,当我检查result[0].Date 时,我得到12/11/2018 12:00:00 AM 而我期待22-Nov-18 12:00:00 AM

我已经读过不同的库/语言对日期值进行不同的序列化。但是,我使用string 来存储值,那么为什么值会发生变化?我想以dd-MMM-yy hh:mm:ss tt 格式接收Date 值。我如何做到这一点?

【问题讨论】:

  • 您确实应该包含足够的代码,以便我们读者可以重现结果。这个问题可能是多方面的。文化覆盖,格式覆​​盖。等等。你真的只需要 entity.DateTimeProperty.ToString("mm/dd/yyyy")。也可能是其他主机只是将数据配置为这种格式,而您现在必须在您这边解析该数据。
  • 包含日期的字符串在通过 JSON 传输时不会改变其格式。这是您的显示逻辑执行此操作。
  • 我没有显示逻辑。我调试我的插件并看到entity.date,我得到"07/11/2018 12:00:00 AM"
  • 是否值得使用反序列化日期格式化程序? stackoverflow.com/questions/21256132/… 见@Foy 的回答。与下面 Rebecca 在此问题中的回答相同,但它是本地的,而不是全局的。
  • 能否请edit 分享字符串returnJson 的值?

标签: c# json asp.net-web-api json.net


【解决方案1】:

所述问题无法在以下测试中重现。

序列化 DTO 然后反序列化 Model 的单元测试行为符合预期

[Test]
public void __String_Dates_Should_Match() {
    //Arrange
    var date = "22-Nov-18 12:00:00 AM";
    var dtoObject = new[] { new DTO { Date = date } };
    var returnJson = JsonConvert.SerializeObject(dtoObject);

    //Act
    var result = JsonConvert.DeserializeObject<IEnumerable<Model>>(returnJson);

    //Assert
    result.First()
        .Should().NotBeNull()
        .And.Match<Model>(_ => _.Date == date);
}

使用内存中 Web API 的集成测试也按预期运行

[TestClass]
public class MyTestClass {
    [Test]
    public async Task __WebApi_Dates_Should_Match() {
        //Arrange
        var date = "22-Nov-18 12:00:00 AM";
        var config = new HttpConfiguration();
        config.MapHttpAttributeRoutes();
        var httpServer = new HttpServer(config);
        var client = new HttpClient(httpServer);

        //Act
        var response = await client.GetAsync("http://localhost/api/test/data");
        var returnJson = await response.Content.ReadAsStringAsync();

        //Assert
        response.IsSuccessStatusCode.Should().BeTrue();

        var result = JsonConvert.DeserializeObject<IEnumerable<Model>>(returnJson);
        result.First()
            .Should().NotBeNull()
            .And.Match<Model>(_ => _.Date == date);
    }
}

[RoutePrefix("api/test")]
public class TestApiController : ApiController {
    [HttpGet]
    [Route("data")]
    public IHttpActionResult Get() {
        var date = "22-Nov-18 12:00:00 AM";
        var dtoObject = new[] { new DTO { Date = date } };
        return Ok(dtoObject);
    }
}

鉴于分配的属性是字符串,它们不应受日期转换的影响。

那么问题将是您如何将DateTime 分配给属性。这可能是代码运行的当前文化的结果。

var value = new DTO { 
    Date = someDateTime.ToString()
};

这是应该应用所需日期格式的地方

var value = new DTO { 
    Date = someDateTime.ToString("dd-MMM-yyyy hh:mm:ss tt")
};

【讨论】:

    【解决方案2】:

    尝试在 WebAPI 配置中使用 ISO-8601 DateTime 格式化程序以获得一致的日期格式:

    JsonSerializerSettings serializerSettings = new JsonSerializerSettings();
    serializerSettings.Converters.Add(new IsoDateTimeConverter());
    GlobalConfiguration.Configuration.Formatters[0] = new JsonNetFormatter(serializerSettings);
    

    然后日期将返回为:

    {
       "Date": "2018-11-20T12:16:00"
    }
    

    在您的客户端中,将 JSON 反序列化为内部对象时,您需要使用相同的格式。

    【讨论】:

    • 我找不到JsonNetFormatter。我需要为这个类添加任何参考吗?顺便说一句,即使值存储在string 类型的变量中,值是否可以在序列化/反序列化时更改?
    • 我无法更改全局设置。有什么办法可以在本地做。
    猜你喜欢
    • 2018-07-16
    • 2020-08-25
    • 2018-02-15
    • 1970-01-01
    • 2010-12-06
    • 1970-01-01
    • 1970-01-01
    • 2016-11-03
    • 1970-01-01
    相关资源
    最近更新 更多