2012-03-02 15 views
8

Tôi gửi ngày từ ứng dụng web của tôi ở định dạng UTC, nhưng khi tôi nhận chúng ở phía máy chủ, bộ nối tiếp JSon (có thể được sử dụng bằng cách thiết lập mô hình của bạn) thực hiện việc này theo ngày địa phương & với DateTimeKind. Địa phương liên quan đến múi giờ của máy chủ.Làm thế nào để nói với ASP.Net MVC rằng tất cả các ngày đến deserialized từ JSon nên được UTC?

Khi tôi thực hiện DateTime.ToUniversalTime() Tôi nhận được ngày UTC đúng, vì vậy đây không phải là vấn đề. Chuyển đổi hoạt động chính xác và ngày được gửi theo cách họ nên ... nhưng .... Tôi không muốn thực hiện cuộc gọi đến 'ToUniversalTime()' vào mỗi ngày trên mô hình của tôi trước khi tôi lưu trữ nó vào cơ sở dữ liệu .. Điều này dễ bị lỗi và dễ quên khi bạn có một ứng dụng lớn.

Vì vậy, đây là câu hỏi: Có cách nào để nói với MVC rằng ngày đến phải luôn được thể hiện bằng định dạng UTC không?

+0

Có vẻ như các deserializer đang làm công việc của mình tốt, nếu các giá trị trong đối tượng DateTime là chính xác. Ngày có thể khó sử dụng nếu bạn bắt đầu đối xử với một số người đặc biệt trên máy chủ. –

+1

@dtryon: Không, tôi nghĩ việc bảo quản chúng như UTC có ý nghĩa hơn rất nhiều. Thời gian địa phương có thể rất mơ hồ - vì vậy deserializer cũng có thể là * mất thông tin * ở đây, đó chắc chắn là một tội lỗi hồng y. –

+0

@JonSkeet nhưng miễn là ToUniversalTime() trả lại đúng UTC, không phải là nó được thể hiện chính xác? –

Trả lời

2

Sau khi tìm hiểu thêm một chút, tôi đã tìm được cách để thực hiện công việc này.

Vấn đề không phải là quá nhiều serializer, chỉ có vấn đề là ngày của mô hình không được thể hiện trong UTC nhưng trong thời gian địa phương. ASP.Net cho phép bạn tạo các chất kết dính mô hình tùy chỉnh và tôi nghĩ đây là chìa khóa để thay đổi ngày thành UTC khi chúng được deserialized.

Tôi đã sử dụng đoạn mã sau để làm cho công việc này, có thể có một vài lỗi để sắt ra, nhưng bạn sẽ có được ý tưởng:

public class UtcModelBinder : DefaultModelBinder 
{ 
    protected override void SetProperty(ControllerContext controllerContext, ModelBindingContext bindingContext, System.ComponentModel.PropertyDescriptor propertyDescriptor, object value) 
    { 
    HttpRequestBase request = controllerContext.HttpContext.Request; 

    // Detect if this is a JSON request 
    if (request.IsAjaxRequest() && 
     request.ContentType.StartsWith("application/json", StringComparison.OrdinalIgnoreCase)) 
    { 
     // See if the value is a DateTime 
     if (value is DateTime) 
     { 
     // This is double casting, but since it's a value type there's not much other things we can do 
     DateTime dateValue = (DateTime)value; 

     if (dateValue.Kind == DateTimeKind.Local) 
     { 
      // Change it 
      DateTime utcDate = dateValue.ToUniversalTime(); 
      if (!propertyDescriptor.IsReadOnly && propertyDescriptor.PropertyType == typeof(DateTime)) 
      propertyDescriptor.SetValue(bindingContext.Model, utcDate); 

      return; 
     } 
     } 
    } 

    // Fall back to the default behavior 
    base.SetProperty(controllerContext, bindingContext, propertyDescriptor, value); 

    } 
} 
Các vấn đề liên quan