2012-12-21 21 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日期將是默認值。 –