Skip to main content Skip to footer

Maintain a Server-based Timestamp in ASP.NET MVC Web Apps Using JSON

When an application includes a timestamp, it's usually reading it from the current machine. If you're in New York, the timestamp is EST; if you're in California, it's Pacific time. In some cases, though, you'll need the app to be consistent with the server time, so that it's consistent everywhere around the world. For example, if you're scheduling a one-day sale, you may want to ensure that the time is static for one time zone; otherwise users will be able to access the sale in their own time zone across the globe.

This post looks at how to maintain a consistent, server-based timestamp in ASP.NET MVC web apps using JSON text. As we know, text is used for transferring data between the server and the client. We always use the text in JSON format.

Json.NET is a popular high-performance JSON framework for .NET to serialize the data into text in JSON format and read the data from a JSON format text. It's used by default for JSON serialization in ASP.NET MVC 6 and ASP.NET Web API.

JSON Serialization

Before an object is transferred to the client, it has to be serialized into JSON text, which will then be parsed into a client object on the client side.

For a DateTime object with different Kinds, it has to be serialized into different texts with Json.NET:

Server (+07:00) Serialization Text Client (+08.00)
2017/1/25 07:00:00 (DateTimeKind.Unspecified) "2017-01-25T07:00:00" 2017/1/25 07:00:00
2017/1/25 07:00:00 (DateTimeKind.Utc) "2017-01-25T07:00:00Z" 2017/1/25 15:00:00
2017/1/25 07:00:00 (DateTimeKind.Local) "2017-01-25T07:00:00+07:00:00" 2017/1/25 08:00:00

In this example, the serialization text keeps the original date and time text, and ends with the time zone, including all the information about the server DateTime object. Using new Date([serialization text]), we can then parse the serialization text into the client object.

However, the Client column shows that only the Unspecified DateTime object keeps the same date and time text as the server. Both the UTC DateTime and the Local objects have different string representations, and they even show different texts in machines with different time zones.

Deserialization

Before a client object is transferred to the server, it has to be serialized into a text; then, on the server, the text is deserialized into an object. A text with the following formats could be deserialized into the corresponding DateTime object by Json.NET:

Serialization Text The DateTime object
"2017-01-25T07:00:00Z" 2017/1/25 O7:00:00(DateKind.Utc)
"2017-01-25T07:00:00+07:00" 2017/1/25 07:00:00(DateTimeKind.Local)
"2017-01-25T07:00:00" 2017/1/25 07:00:00(DateTimeKind.Unspecified)

Looking at the table above, we can follow three guidelines:

  • If we want to get a UTC format DateTime object in the server, we should serialize the client object into a text with a fixed format that ends with “Z.”
  • If the text ends with “+hh:mm” or “-hh:mm,” it will be deserialized into a Local DateTime object.
  • If the text ends in another way, it will be deserialized into an Unspecified DateTime object.

For some applications, the user only focuses on the date and the time without the time zone for the Date field. In other words, the user wants the application to reflect the server’s date and time, instead of whatever time zone they’re in. So how do we make this happen?

Show the server date and time, not the client's

If we want to keep the date and the time the same for both the server and client, we need to apply transformations in two parts:

Transformation Part 1: Serialization (from the server to the client)

For the UTC format DateTime object, the client Date object will be generated with this code:

new Date("2017-01-25T07:00:00Z");

The object shows different texts from the server. If we remove the time zone text from the serialization text, and use that text to generate a client local Date object, the date and time match the server, which solves the problem about the client Date text.

new Date("2017-01-25T07:00:00");

Transformation Part 2: Deserialization (from the client to the server)

Now we'll let the server get the same Kind and correct DateTime object after the previous transformation is complete. (Without the previous transformation, the server gets the wrong DateTime object.)

After the transformation from the client to the server, get a client local Date object:

2017/01/25 7:00(+08:00).

Serialize the local Date object into the following text by the JSON.stringify() method:

2017-01-24T23:00:00Z

After deserialization, we'll get the server DateTime object:

2017/01/24 23:00(Utc).

However, we see that the object has changed and different from its original value (2017/01/25 7:00(Utc)), which means it's incorrect.

If we add a customization on the serialization of the client object to get the following text, we get the correct DateTime object in the server:

2017-01-25T07:00:00Z,

We can make these transformations on the server or client side, which offers two possible solutions:

1. Make Transformations on the Server

The Unspecified DateTime can keep the date and the time, so we can convert all the DateTime objects on the server to Unspecified and convert them back when necessary.

The DateTimeFields sample shows you how to make these transformations. Get the sample.

Although it seems like a simple solution, we need to pay close attention to the conversions and not miss any transformations. Otherwise, there could be an unexpected problem.

2. Make Transformations on the Client Side

On the client side, we need to customize the parsing for the Date text and the serialization for the client Date object. Our MVC components provide two client events that support these transformations: OnClientReponseTextParsing and OnClientRequestDataStringifying.

1) OnClientReponseTextParsing

This event, which is fired when parsing the JSON text, allows us to customize the parsing to generate the desired client Date object.

We can get following information from the event argument:

  • key: The name of the item text to be parsed
  • value: The text of the item to be parsed
  • result: Specifies the value to which you want to parse the text. You can set its value to an appropriate client object.
  • cancel: If you don't want the default parsing, specify its value to true. Then you can specify the value for result.

2) OnClientRequestDataStringifying

This event is fired when we serialize the client object into the text; it's then sent to the server and deserialized into the server object. In this event, we can customize the serialization and generate the text with the appropriate format.

We can get following information from the event argument:

  • key: The name of the item text to be serialized
  • value: The text of the item to be serialized. Here, the value is a client object.
  • result: Specifies the text to which the object should be serialized. Set its value to whatever text you want.
  • cancel: If you don't want the default serialization, specify it to true. Then you can set the value for result to whatever text you want.

This solution is easier for the user. They only need to focus on these two events and make the transformations in the events.

The DateTimeFields sample also shows how to make transformations this way. Get the sample.

MESCIUS inc.

comments powered by Disqus