user915331
user915331

Reputation:

Somehow the client detects the server's time zone in WCF

I have this scenario:

Server is in (GMT +3) time zone

Client is in (GMT -5) time zone

Server returns a DateTime to the client, let's say it is "10JAN2013 00:00" and AFAIK the DateTime has no time zone info attached to it. The time in the client side is converted into the client's time zone which is "09JAN2013 16:00"! the DTK is specified to DTK.Unspecified.

My question, how did the client know the time zone of the server if the DateTime has no timezone information? this is confusing to me! Is it sent in the header of SOAP or something like that?

Upvotes: 2

Views: 919

Answers (1)

carlosfigueira
carlosfigueira

Reputation: 87228

They may or may not know. When DateTime objects are passed between client and server, they're serialized into some common format understood by the two parties. In some of those formats, such as XML, the time zone information is sent across the wire: if you have a DateTime with DateTimeKind.Utc, a 'Z' will be appended to the serialized date; for Local the timezone will be added, and for Unspecified nothing will be added, so the other party knows which format to use. In other formats, such as JSON, the server will not send anything in the date time if the kind is Utc, but will add the local time zone information for the other kinds (there's no distinction in the JSON format for Local and Unspecified; IIRC the receiving party will treat such information as Local).

If you want to see what goes on the wire, you can run the program below, while having a network capture tool such as Fiddler, to see what the client is sending to the server.

public class StackOverflow_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();
    }
}

Upvotes: 1

Related Questions