客户端以某种方式在 WCF 中检测到服务器的时区

Posted

技术标签:

【中文标题】客户端以某种方式在 WCF 中检测到服务器的时区【英文标题】:Somehow the client detects the server's time zone in WCF 【发布时间】:2012-12-17 10:34:54 【问题描述】:

我有这种情况:

服务器位于 (GMT +3) 时区

客户在 (GMT -5) 时区

服务器向客户端返回一个DateTime,假设它是“10JAN2013 00:00”,AFAIK DateTime 没有附加时区信息。客户端的时间转换成客户端的时区,即“09JAN2013 16:00”! DTK 被指定为 DTK.Unspecified。

我的问题,如果DateTime 没有时区信息,客户端如何知道服务器的时区?这让我很困惑!它是在 SOAP 标头中发送的还是类似的?

【问题讨论】:

【参考方案1】:

他们可能知道也可能不知道。当DateTime 对象在客户端和服务器之间传递时,它们被序列化为双方都能理解的某种通用格式。在其中一些格式中,例如 XML,时区信息是通过网络发送的:如果您有一个 DateTimeDateTimeKind.Utc,则将在序列化日期后附加一个“Z”;对于Local,将添加时区,对于Unspecified,将不添加任何内容,因此对方知道使用哪种格式。对于其他格式,例如JSON,如果类型是Utc,服务器将不会在日期时间发送任何内容,但会添加其他类型的本地时区信息(Local的JSON格式没有区别和Unspecified;IIRC 接收方会将此类信息视为Local)。

如果您想查看网络上发生了什么,您可以运行下面的程序,同时拥有 Fiddler 等网络捕获工具,以查看客户端向服务器发送的内容。

public class ***_14132566

    [ServiceContract]
    public interface ITest
    
        [OperationContract]
        [WebInvoke(RequestFormat = WebMessageFormat.Json, 
                   ResponseFormat = WebMessageFormat.Json,
                   BodyStyle = WebMessageBodyStyle.WrappedRequest)]
        DateTime Add10Hours(DateTime input, string description);
    
    public class Service : ITest
    
        public DateTime Add10Hours(DateTime input, string description)
        
            return input.AddHours(10);
        
    
    public static void Test()
    
        string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
        ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress));
        host.AddServiceEndpoint(typeof(ITest), new BasicHttpBinding(), "basic");
        host.AddServiceEndpoint(typeof(ITest), new WebHttpBinding(), "web").Behaviors.Add(new WebHttpBehavior());
        host.Open();
        Console.WriteLine("Host opened");

        ChannelFactory<ITest> factory = new ChannelFactory<ITest>(new BasicHttpBinding(), new EndpointAddress(baseAddress + "/basic"));
        ITest proxy = factory.CreateChannel();
        Console.WriteLine(proxy.Add10Hours(new DateTime(2013, 1, 2, 19, 29, 0, DateTimeKind.Utc), "XML, UTC"));
        Console.WriteLine(proxy.Add10Hours(new DateTime(2013, 1, 2, 19, 29, 0, DateTimeKind.Local), "XML, Local"));
        Console.WriteLine(proxy.Add10Hours(new DateTime(2013, 1, 2, 19, 29, 0, DateTimeKind.Unspecified), "XML, Unspecified"));

        ((IClientChannel)proxy).Close();
        factory.Close();

        factory = new ChannelFactory<ITest>(new WebHttpBinding(), new EndpointAddress(baseAddress + "/web"));
        factory.Endpoint.Behaviors.Add(new WebHttpBehavior());
        proxy = factory.CreateChannel();
        Console.WriteLine(proxy.Add10Hours(new DateTime(2013, 1, 2, 19, 29, 0, DateTimeKind.Utc), "JSON, UTC"));
        Console.WriteLine(proxy.Add10Hours(new DateTime(2013, 1, 2, 19, 29, 0, DateTimeKind.Local), "JSON, Local"));
        Console.WriteLine(proxy.Add10Hours(new DateTime(2013, 1, 2, 19, 29, 0, DateTimeKind.Unspecified), "JSON, Unspecified"));

        ((IClientChannel)proxy).Close();
        factory.Close();

        Console.Write("Press ENTER to close the host");
        Console.ReadLine();
        host.Close();
    

【讨论】:

有没有办法阻止这种行为并使时间在没有时区信息的情况下通过网络发送? 如果你总是使用Utc 次,那么就不会有TZI。每当您有一个要转移的DateTime 对象时,请在其上调用ToUniversalTime()

以上是关于客户端以某种方式在 WCF 中检测到服务器的时区的主要内容,如果未能解决你的问题,请参考以下文章

在客户端检测时区[重复]

WCF、安全和证书

Restful WCF 服务和 LINQ

WCF 客户端缓存 Windows 身份验证

WCF 通过 MSMQ 到 WCF 请求和响应

在 WCF 双工合同中检测客户端死亡