jsonasp.net-mvcdatedatacontractjsonserializer

ASP.NET MVC controller losing a day on conversion


I'm sending some data from a local application to another one (ASP.NET MVC). The data is an array of DTOs. I am testing this on my local machine.

The local application is a Web Forms and is sending the data using a service. I do not use JsonResult.

The serialzed DTO is sent correctly, but the dates are deserialized incorrectly on the MVC side, being a day behind then the ones sent.

The DTO class looks like this:


    [DataContract]
    public class ProjectInfoDto
    {
        [DataMember]
        public long ProjectId { get; set; }

        [DataMember]
        public string ProjcetCode { get; set; }

        [DataMember]
        public DateTime BeginDate { get; set; }

        [DataMember]
        public DateTime FinalDate { get; set; }
    }

I am serializing the data using the below method:

public static string JsonSerialize<T>(T obj)
{
    var serializer = new DataContractJsonSerializer(obj.GetType());
    var ms = new MemoryStream();
    serializer.WriteObject(ms, obj);
    string retVal = Encoding.Default.GetString(ms.ToArray());
    ms.Dispose();
    return retVal;
}

The JSON sent to the MVC application looks like this (with correct dates):


{"ProjectId":"222","ProjcetCode":"OP9089","BeginDate":"/Date(1461790800000+0300)/","FinalDate":"/Date(1557435600000+0300)/" }

The method receiving the data looks like this:

public ActionResult GetProjectData(ProjectInfoDto[] info) {...}

The original dates are (from the database):

BeginDate -> 2016-04-28 00:00:00.000

FinalDate -> 2019-05-10 00:00:00.000

The dates on the MVC side when looking at the received array:

BeginDate -> 2016-04-27 00:00:00.000

FinalDate -> 2019-05-09 00:00:00.000

I don't know why the dates are a day behind when received.


Solution

  • I found a suggestion in this question Is there a way to override how DataContractJsonSerializer serializes Dates?.

    The answer in the question suggests creating an instance method and decorate it using the

    [OnSerializing]
    attribute. This will allow custom serialization for certain attributes.

    Full code below:

    [DataContract]
    public class ProjectInfoDto
    {
        [DataMember(Name = "BeginDate")]
        private string beginDate;
    
        [DataMember(Name = "ExecutieDataFinal")]
        private string finalDate;
    
        [DataMember]
        public long ProjectId { get; set; }
    
        [DataMember]
        public string ProjcetCode { get; set; }
    
        public DateTime BeginDate { get; set; }
    
        public DateTime FinalDate { get; set; }
    
        [OnSerializing]
        void OnSerializing(StreamingContext context)
        {
            beginDate = BeginDate.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture);
            finalDate = FinalDate.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture);
        }
    }
    

    The idea is to leave the DateTime properties intact, and use the private string fields for the serialzation. In the OnSerializing method, you convert the DateTime properties to the required format. As per the suggestions in the comments to my question, I used the ISO-8601 format ("yyyy-MM-dd").