2012-12-21 60 views
1

我在Breeze的JsonMediaTypeFormatter的设置中遇到问题。 我会做的是,由WebAPI 发送和接收的json日期始终以UTC工作。Breeze的WebApi控制器如何使用UTC DateTime?

this document,它将通过为JsonSerializerSettings

但是没有工作的性质DateTimeZoneHandling设置为DateTimeZoneHandling.Utc成为可能。

调查this source code,我意识到可能会影响此行为的是对this other issue所做的破解。

通过删除所有此代码的波纹管,一切正常。

//jsonSerializerSettings.Converters.Add(new IsoDateTimeConverter 
    //{ 
    // DateTimeFormat = "yyyy-MM-dd\\THH:mm:ss.fffK" 
    //}); 

我该如何处理这种情况而不必删除Hack?

编辑1

我第一次设置尝试如下:

var jsonFormatter = Breeze.WebApi.JsonFormatter.Create(); 
jsonFormatter.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Utc; 
jsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/json")); 
jsonFormatter.SupportedEncodings.Add(new UTF8Encoding(false, true)); 
GlobalConfiguration.Configuration.Formatters.Insert(
      0, jsonFormatter); 

但这并没有工作,返回的日期是不是在UTC。

EDIT 2

首先,我已经更新了微风LIB到0.80.3版本。

在我App_Start文件夹我有这个BreezeWebApiConfig.cs文件:

[assembly: WebActivator.PreApplicationStartMethod(
    typeof(Partner.App_Start.BreezeWebApiConfig), "RegisterBreezePreStart")] 
namespace Partner.App_Start 
{ 
    public static class BreezeWebApiConfig 
    { 
     public static void RegisterBreezePreStart() 
     { 
      GlobalConfiguration.Configuration.Routes.MapHttpRoute(
       name: "BreezeApi", 
       routeTemplate: "api/{controller}/{action}" 
      ); 

      var jsonFormatter = Breeze.WebApi.JsonFormatter.Create(); 
      jsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/json")); 
      jsonFormatter.SupportedEncodings.Add(new UTF8Encoding(false, true)); 

      GlobalConfiguration.Configuration.Formatters.Insert(
       0, jsonFormatter); 

      // Apply query parameters, expressed as OData URI query strings, 
      // to results of Web API controller methods that return IQueryable<T> 
      GlobalConfiguration.Configuration.Filters.Add(
       new Breeze.WebApi.ODataActionFilter()); 
     } 
    } 
} 

其次,我创建了一个CustomBreezeConfig.cs类(周杰伦下面描述的代码),一,我叫BreezeConfig文件夹中,但这个新的尝试没有奏效。

问候,

贝尔纳多·帕切科

回答

1

请尝试微风v 0.80.5以及相应的发行说明。希望'时间现在应该正确地往返。

+0

请让我们知道这是否解决了它。如果是这样,请检查答案下的复选标记。这样做会帮助我们解决这个问题。谢谢。 – Ward

+0

@Jay我保留了相同的代码(上面描述的BreezeWebApiConfig.cs类和CustomBreezeConfig.cs类)并更新至v 0.80.5。但是,服务器发送给客户端的json日期仍然不是UTC(最后没有Z)。问候。 –

+0

Bernardo,它不会是,但它会在客户端上正确转换(到UTC日期)这就是DataType.parseDateFromServer方法的作用。所以看看当时调用返回的结果中的日期。 –

1

当你说添加DateTimeZoneHandling没有工作,你怎么尝试设置呢?

你可以尝试在源代码中直接在上面的'Converters.Add'调用上面添加这一行(不删除'hack'),并让我知道它是否有效。

jsonSerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Utc; 

我同意它仍然笨拙,因为这意味着你必须修改微风源。所以如果它确实起作用了,我们会试着想出一些方法来让你从格式化程序之外设置它。请告诉我们。

+0

GitHub中的最新[BreezeController]属性应该会使您的格式化程序更容易地交付给控制器。该属性将被发布并很快出现在NuGet包中。这种改进并不能让您轻松扩展Breeze JsonFormatter。你必须自己写一个。幸运的是,Breeze的最低要求很少,因此重新实施该组件本身并不是太难。 – Ward

+0

@Jay嗨Jay,我编辑我的问题,我第一次尝试设置DateTimeZoneHandling。我试图做你说的,但返回的日期不是UTC。提前致谢。 –

+0

如果当你说'返回'你的意思是'返回'到服务器,而不是客户端,那么我确实理解这个问题。 Breeze目前使用两个序列化器,一个用于查询,一个用于保存。上面给出的定制是为了从'服务器'序列化到'客户端',以定制保存序列化,您需要在'ContextProvider.saveChanges'方法中破解源代码以使用定制的json序列化程序。我们将尝试在下一个版本中实现可插拔。 –

0

我解决了这个hack的utc问题,它仍然有味道。

在app.vm.run.js

app.vm.run = (function ($, ko, dataservice, router) { 
var currentRunId = ko.observable(), 
    // run will be an entity 
    run = ko.observable(), 
... 
    save = function() { 
     this.run().lastUpdate(makeDatetimeUTC(moment().toDate())); 
     this.run().runStart(makeDatetimeUTC(this.run().runStart())); 
     this.run().runEnd(makeDatetimeUTC(this.run().runEnd())); 
     dataservice.saveChanges(); 
     // the test r === run() succeeds because the local run is a 
     // ko.observable which is bound to the run in the cache 
     var r = dataservice.getRunById(currentRunId()); 
    }, 
... 

})($, ko, app.dataservice, app.router); 
在myScripts

。JS

// Here is a real pain in the neck. 
// For some reason, when the entity is saved, it shows up on the server as UTC datetime 
// instead of local. Moment parses everything as local by default, so the formatDate function 
// used to get a display value needs to be converted to utc before it is returned to the server. 
// 
// This function takes the value of the dependentObservable in the entity 
// and converts it to a string which can be stored back into the entity before sending 
// it to the server. 
// 
// The reason I need to do that is so that it displays properly after the save.  
// The date seems to be handled properly by the server. 

var makeDatetimeUTC = function(localDatetime) { 
    var datestring = formatDate(localDatetime); 
    var utc = moment.utc(datestring); 
    return formatDate(utc); 
}; 

var formatDate = function(dateToFormat) { 
    if (dateToFormat === null ||dateToFormat === undefined || dateToFormat.length === 0) 
     return ""; 

    // intermediate variable is not needed, but is good for debugging 
    var formattedDate = moment(dateToFormat).format('MM/DD/YYYY hh:mm A'); 
    return formattedDate; 
    }, 
    formatObservableDate = function(observable) { 
     if (ko.isObservable(observable)) 
      return observable(formatDate(observable())); 
     else 
      throw new Error("formatObservableDate expected a ko.Observable "); 
    }; 
2

随着微风v 0.80.3的,我们已经添加到自定义JSON序列化设置,微风两个查询使用和保存能力。它涉及添加一个服务器端类,该类是新的Breeze.WebApi.BreezeConfig类的子类。这个子类看起来像:

public class CustomBreezeConfig : Breeze.WebApi.BreezeConfig { 

    /// <summary> 
    /// Overriden to create a specialized JsonSerializer implementation that uses UTC date time zone handling. 
    /// </summary> 
    protected override JsonSerializerSettings CreateJsonSerializerSettings() { 
     var baseSettings = base.CreateJsonSerializerSettings(); 
     baseSettings.DateTimeZoneHandling = DateTimeZoneHandling.Utc; 
     return baseSettings; 
    } 
    } 

Breeze.WebApi.BreezeConfig的子类出现在服务器端项目现在将自动发现并使用定制微风的配置的任何实例。

请让我们知道这是否有帮助(或不)。

+0

嗨周杰伦,感谢您的修复,但不幸的是它没有奏效。我用我正在使用的代码编辑我的问题,以便看看我是否做错了什么。从客户端发送到服务器的json中的日期适用于UTC,但从服务器发送到客户端的json日期不是UTC。例如,从服务器发送到客户端的日期必须是2012-12-28T00:00:00.000Z,而不是2012-12-28T00:00:00.000。问候。 –

+1

好吧,我想我明白发生了什么事。事实证明,EF/SQL服务器不存储时区信息,因此当您在EF上存储时间并稍后检索时,检索到的数据时间将其时区设置为“未指定”。当这个信息被发送回javascript客户端时,没有可用的时区信息发送(因此缺少'Z')。事实证明,IE和Chrome将缺少的时区说明符解释为代表UTC日期,而Firefox则将同一事物解释为本地日期。我猜你正在使用Firefox。它是否正确? –

+0

继续之前的评论。请确认这是否合理。我们现在正在考虑添加一个设置,以指示您是否希望将从服务器返回的日期视为UTC日期或本地日期。 UTC日期将是默认值。 –