错误请求 - Post 方法 - JSON DateTime 问题

Posted

技术标签:

【中文标题】错误请求 - Post 方法 - JSON DateTime 问题【英文标题】:Bad Request -Post method - JSON DateTime issue 【发布时间】:2016-08-22 16:44:20 【问题描述】:

我有一个 Visual Studio (2015) 项目,其中包括一个客户端部分 (Xamarin.Forms PCL) 和一个 Web 服务部分 (WCF Rest)。 Web 服务使用 edmx 与数据库通信 (SQL Server 2016)。 JSON 用于交换数据。

我是创建/使用 WCF Rest 服务的新手。我使用 GET 方法没有问题,但我遇到了 POST 方法的问题。

此方法是运行良好的服务的一部分:基于 GET 的方法没有问题。当我从 URL 或我的客户端 (PCL Xamarin.Forms) 对其进行测试时,它运行良好。

POST 方法(我的第一次)有点问题。

它应该在 SQL Server (2016) 的表中创建一个新记录。

当我使用 Postman (https://www.getpostman.com/) 对其进行测试时,它已经出现了一个问题:它在表中创建了一条记录,但该对象有两个日期,并且这两个日期被替换为 1970-01-01。

当我使用我的客户端联系网络服务时:我收到“错误请求”。

我寻找了一个解决方案,发现与其放置 Datetime 值,不如放置从 1970-01-01 开始的毫秒数。

我在 Postman 中使用了这个建议,发现新行的创建效果很好。

邮递员请求的正文:


"Reservation_Utilisateur_Id" : "4", 
"Reservation_Velo_Id" : "2",
"Reservation_DateDebut" : "\/Date(1245398693390)\/",
"Reservation_PeriodeDebut" : "matin",
"Reservation_DateFin" :"\/Date(1245398693390)\/", 
"Reservation_PeriodeFin" : "matin"
 

现在,我想知道如何将该对象发送到服务器。如何像上面那样序列化我的对象?

我寻找解决方案没有成功。

我不断收到“反序列化 BikeSharingService.Reservation 类型的对象时出错。DateTime 内容 '2016-08-22T00:00:00+02:00' 不以 '/Date(' 开头并以')/' 根据 JSON 的要求。”

有人可以给新手我是一个解释,也许是一些有效的代码吗?

这是我的代码:

我的合同:

    [OperationContract]
    [WebInvoke(Method = "POST", UriTemplate = "create",
        ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json)]
    Reservation create(Reservation reservation);

服务方式:

    public Reservation create(Reservation reservation)
    
        using (MyEntities bse = new MyEntities())
         
                Reservation re = new Reservation
                
                    Reservation_Utilisateur_Id = reservation.Reservation_Utilisateur_Id,
                    Reservation_Velo_Id = reservation.Reservation_Velo_Id,
                    Reservation_DateDebut = reservation.Reservation_DateDebut,
                    Reservation_PeriodeDebut = reservation.Reservation_PeriodeDebut,
                    Reservation_DateFin = reservation.Reservation_DateFin,
                    Reservation_PeriodeFin = reservation.Reservation_PeriodeFin,
                    Reservation_DemandeRecupDomCli = reservation.Reservation_DemandeRecupDomCli

                ;
                bse.Reservations.Add(re);
                bse.SaveChanges();
            return re;
        
    

在客户端:

   const string Url1 = "http://localhost:51843/ServiceReservation.svc/create";

   public async Task<Reservation> create(Reservation reservation)
    
            string json = JsonConvert.SerializeObject(reservation);
            var client = new HttpClient();
            client.DefaultRequestHeaders.Add("Accept", "application/json");
            var response = await client.PostAsync(Url1,
                            new StringContent(
                               json,
                            Encoding.UTF8, "application/json"));
                            return  JsonConvert.DeserializeObject<Reservation>(
            await response.Content.ReadAsStringAsync());            
    

然后在客户端调用方法:

        Reservation re =new Reservation();
        re.Reservation_Utilisateur_Id = 4;
        re.Reservation_Velo_Id = 2;
        re.Reservation_DateDebut = DateTime.Now.Date;
        re.Reservation_PeriodeDebut = "matin";
        re.Reservation_DateFin = DateTime.Now.Date;
        re.Reservation_PeriodeFin = "matin";
        re.Reservation_DemandeRecupDomCli = 1;

        Reservation resultat = await reManager.create(re);

我得到了什么:

错误的错误请求方法:POST,RequestUri: 'http://localhost:51843/ServiceReservation.svc /create',版本:2.0, 内容:System.Net.Http.StringContent,标题: 接受: 应用程序/json 内容类型:应用程序/json;字符集=utf-8 内容长度:407 错误请求 1.1

反序列化类型对象时出错 BikeSharingService.Reservation。日期时间内容 '2016-08-22T00:00:00+02:00' 不以 '/Date(' 开头并以 JSON 所需的 ')/'。

【问题讨论】:

Json 没有定义标准的日期格式,但值得注意的是,Json.Net(被 .Net 框架的面向 Web 的部分大量使用)支持多种格式(甚至自定义的)因此,如果您可以决定适用于所有客户端的标准,则可以配置 Json(en/de)编码以本地使用它。请参阅newtonsoft.com/json/help/html/datesinjson.htm 了解更多信息 @Basic 非常感谢。我使用了您建议的页面上提供的以下信息并且它有效。如此简单,实际上:-) JsonSerializerSettings microsoftDateFormatSettings = new JsonSerializerSettings DateFormatHandling = DateFormatHandling.MicrosoftDateFormat ; string microsoftJson = JsonConvert.SerializeObject(entry, microsoftDateFormatSettings); 【参考方案1】:

[从评论中推荐]

Json 没有定义标准的日期格式,但值得注意的是 Json.Net(被 .Net 框架的大多数面向 Web 的部分使用)支持开箱即用的多种格式(甚至自定义那些)。

如果您可以确定适用于所有客户端的标准,则可以在 .Net 中配置 Json(en/de)编码以在本地使用它。

有关如何指定日期格式处理程序的更多信息和详细信息,请参阅http://newtonsoft.com/json/help/html/datesinjson.htm。

[链接中的示例代码]

public void WriteJsonDates()

    LogEntry entry = new LogEntry
    
        LogDate = new DateTime(2009, 2, 15, 0, 0, 0, DateTimeKind.Utc),
        Details = "Application started."
    ;

    // default as of Json.NET 4.5
    string isoJson = JsonConvert.SerializeObject(entry);
    // "Details":"Application started.","LogDate":"2009-02-15T00:00:00Z"

    JsonSerializerSettings microsoftDateFormatSettings = new JsonSerializerSettings
    
        DateFormatHandling = DateFormatHandling.MicrosoftDateFormat
    ;
    string microsoftJson = JsonConvert.SerializeObject(entry, microsoftDateFormatSettings);
    // "Details":"Application started.","LogDate":"\/Date(1234656000000)\/"

    string javascriptJson = JsonConvert.SerializeObject(entry, new JavaScriptDateTimeConverter());
    // "Details":"Application started.","LogDate":new Date(1234656000000)

【讨论】:

【参考方案2】:

您尝试使用的是Epoch DateTime 或Unix DateTime。

要将 DateTime 对象转换为纪元日期时间,您可以创建一个辅助方法。它是从 1970 年 1 月 1 日开始的毫秒或秒。

此外,如果需要,您可以使用 Noda DateTime 代替具有转换方法的 .NET。

您可以为 DateTime 创建一个具有 string 数据类型的新类,并指定一个 Casting。或者您可以编写自定义序列化方法。

序列化后的默认日期时间格式为ISO 8601 Format。

转换为 Unix 或 Epoch 日期时间的代码:

private static readonly DateTime EpochDateTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);

public static long ConvertDateTimeToUnixTime(DateTime date, bool isDatarequiredInMilliSeconds = false, DateTimeKind dateTimeKind = DateTimeKind.Local)

     return Convert.ToInt64((DateTime.SpecifyKind(date.Value, dateTimeKind).ToUniversalTime() - EpochDateTime).TotalSeconds) * (isDatarequiredInMilliSeconds ? 1000 : 1);

如果需要转换回来可以使用下面的(source):

var milliseconds = "/Date(1245398693390)/".replace(/\/Date\((-?\d+)\)\//, '$1');
var actualDate = new Date(parseInt(milliseconds));

【讨论】:

感谢您抽出宝贵时间回答。我实际上使用了 Basic 建议的 JsonConverter 并且它有效。无论如何,感谢您接听我的求助电话。

以上是关于错误请求 - Post 方法 - JSON DateTime 问题的主要内容,如果未能解决你的问题,请参考以下文章

错误请求 - Post 方法 - JSON DateTime 问题

Json 消费的 Jersey Post 请求 405 错误

发生错误 400(错误请求)时,使用 Axios 从 POST 捕获返回 json

linux shell中curl 发送post请求json格式问题

AJAX POST 上的 JSON Stringify 400 错误请求

如何在ajax post方法中发送json请求