2012-12-21 2 views
1

Breeze의 JsonMediaTypeFormatter 설정에 문제가 있습니다. 내가하는 것은 WebAPI 에 의해 보내고받는 json의 날짜가 항상 UTC에서 작동한다는 것입니다.Breeze의 WebApi 컨트롤러가 UTC DateTime과 함께 작동하는 방식은 무엇입니까?

this document에 따르면, 그것은 작동하지 않았다 그러나 JsonSerializerSettings

에 대한 DateTimeZoneHandling.Utc에 재산 DateTimeZoneHandling을 설정함으로써 가능할 것이다.

this source code을 조사한 결과,이 동작에 영향을 미칠 수있는 것이 this other issue에 대해 수행 된 해킹임을 깨달았습니다.

이 코드를 모두 제거하면 모든 것이 정상적으로 작동합니다.

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

어떻게 해킹을 제거하지 않고도이 상황을 처리 할 수 ​​있습니까?

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 1

내 첫 번째 시도였다.

편집 2

첫째, 나는 0.80.3 버전으로 바람 lib에 업데이트되었습니다. 내 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

해당 릴리스 노트와 함께 breeze 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'호출 바로 위에서 ('해킹'을 제거하지 않고)이 행을 추가하고 작동하는 경우 알려 주시기 바랍니다.

jsonSerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Utc; 

나는 breeze 소스를 수정해야한다는 말은 아직도 어색하다는 데 동의합니다. 그래서 작동한다면, 우리는 포맷터 외부에서 이것을 설정할 수있는 방법을 찾아 낼 것입니다. 저희에게 알려주십시오.

+0

GitHub의 최신 [BreezeController] 속성은 포맷터를 컨트롤러에보다 쉽게 ​​전달할 수 있어야합니다. 그 속성은 곧 출시되어 NuGet 패키지에 곧 나타납니다. 이러한 개선으로 Breeze JsonFormatter를 쉽게 확장 할 수는 없습니다. 당신은 그 중 하나를 직접 써야 할 것입니다. 다행스럽게도 Breeze의 최소 요구 사항은 거의 없으므로 해당 구성 요소를 직접 다시 구현하는 것은 어렵지 않습니다. – Ward

+0

@Jay Hi Jay, DateTimeZoneHandling을 설정하려는 첫 번째 시도로 내 질문을 편집했습니다. 내가 말한 것을 시도했지만 반환 된 날짜가 UTC가 아닙니다. 미리 감사드립니다. –

+0

'반품'이라고 말하면 클라이언트가 아니라 서버에 '반품 됨'을 의미하는 경우 문제를 이해합니다. Breeze는 현재 쿼리 용과 저장 용의 두 가지 serializer를 사용합니다. 위의 커스터마이징은 '서버'에서 '클라이언트'로 직렬화하여 사용자 정의 json 시리얼 라이저를 사용하기 위해 'ContextProvider.saveChanges'메소드에서 소스를 해킹해야하는 저장 직렬화를 사용자 정의하는 것입니다. 우리는 다음 릴리스에서 이것을 플러그 가능하도록 만들려고 노력할 것입니다. –

0

나는 여전히이 냄새가 나는이 해킹으로 utc 문제를 해결했습니다. myScripts에서 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); 

에서

.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

breeze v 0.80.3부터 breeze가 쿼리와 저장에 모두 사용하는 json serializer 설정을 사용자 정의하는 기능이 추가되었습니다. 여기에는 새로운 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.000 대신 2012-12-28T00 : 00 : 00.000Z가되어야합니다. 문안 인사. –

+1

좋아, 무슨 일이 일어나고 있는지 알 것 같아. EF/SQL 서버는 표준 시간대 정보를 저장하지 않으므로 EF에 시간을 저장하고 나중에 검색 할 때 검색된 데이터 시간은 '지정되지 않음'으로 설정된 시간대를가집니다. 다음이 자바 스크립트 클라이언트로 다시 보낼 때 보낼 수있는 시간대 정보가 없습니다 (따라서 누락 된 'Z'). IE와 Chrome은 누락 된 시간대 지정자를 UTC 날짜를 나타내는 것으로 해석하지만 Firefox는 현지 날짜와 동일한 것을 해석합니다. 나는 당신이 Firefox를 사용하고 있다고 생각하고 있습니다. 이 올바른지? –

+0

이전 댓글을 계속합니다. 이것이 의미가 있는지 확인하십시오. 서버에서 반환 된 날짜를 UTC 날짜 또는 현지 날짜로 처리할지 여부를 결정하는 설정을 추가하는 방법에 대해 알아 보았습니다. UTC 날짜가 기본값이됩니다. –

관련 문제