Skip to content

Local timezone added when deserializing Model having DateTime property #145

Open
@gunmeet

Description

@gunmeet

I have a model containing a DateTime property. When I am trying to fetch the saved property from memcached local timezone is added to the datetime value. How can I get exactly the same datetime value that I'm saving?

Response from the API

{
    "original": {
        "effectiveDate": "2020-06-29T16:45:18.235"   // This is what I am saving in memcached
    },
    "fromCache": {
        "effectiveDate": "2020-06-29T16:45:18.235+05:30"  // When I fetch it from memcached, local timezone is added
    },
    "originalDate": "2020-06-29T16:45:18.235", // primitive datetime
    "fromCacheDate": "2020-06-29T16:45:18.235", // fetched from cache, primitive datetime works fine
    "jsonSerializerDesserialize": {
        "EffectiveDate": "2020-06-29T16:45:18.235+05:30" // Using BsonDataWriter & JsonSerializer. This is used in DefaultTranscoder.cs
    },
    "jsonConvertDeserialize": {
        "EffectiveDate": "2020-06-29T16:45:18.235" // using JsonConvert.Serialize works fine
    }
}

DefaultTranscoder.cs

WeatherForecastController.cs

using System;
using System.IO;
using System.Threading.Tasks;
using Enyim.Caching;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using Newtonsoft.Json.Bson;

namespace memcachedtester.Controllers
{
    [ApiController]
    [Route("[controller]")]
    public class WeatherForecastController : ControllerBase
    {
        private readonly IMemcachedClient _memcachedClient;

        public WeatherForecastController(IMemcachedClient memcachedClient)
        {
            _memcachedClient = memcachedClient;
        }

        [HttpGet]
        public async Task<dynamic> Get()
        {
           DateTime value = new DateTime(2020, 6, 29, 16, 45, 18, 235);

            string key = "date";

            DateTimeModel mappingRestrictionModel = new DateTimeModel
            {
                EffectiveDate = value
            };

            await _memcachedClient.SetAsync(key, mappingRestrictionModel, 120);
            var r = await _memcachedClient.GetValueAsync<DateTimeModel>(key);

            string key2 = "date2";
            await _memcachedClient.SetAsync(key2, value, 120);
            var r2 = await _memcachedClient.GetValueAsync<DateTime>(key2);

            var q = this.SerializeObject(mappingRestrictionModel);
            var w = this.DeserializeObject(q);

            var q1 = JsonConvert.SerializeObject(mappingRestrictionModel);
            var w1 = JsonConvert.DeserializeObject(q1);


            var t = new TestClass
            {
                Original = mappingRestrictionModel,
                FromCache = r,
                OriginalDate = value,
                FromCacheDate = r2,
                JsonSerializerDesserialize = w,
                JsonConvertDeserialize = w1,
            };

            return t;
        }

        protected virtual ArraySegment<byte> SerializeObject(object value)
        {
            using (var ms = new MemoryStream())
            {
                using (var writer = new BsonDataWriter(ms))
                {
                    var serializer = new JsonSerializer();
                    serializer.Serialize(writer, value);
                    return new ArraySegment<byte>(ms.ToArray(), 0, (int)ms.Length);
                }
            }
        }

        protected virtual object DeserializeObject(ArraySegment<byte> value)
        {
            using (var ms = new MemoryStream(value.Array, value.Offset, value.Count))
            {
                using (var reader = new BsonDataReader(ms))
                {
                    JsonSerializer serializer = new JsonSerializer();
                    return serializer.Deserialize(reader);
                }
            }
        }
    }

    public class TestClass
    {
        public DateTimeModel Original { get; set; }
        public DateTimeModel FromCache { get; set; }
        public DateTime OriginalDate { get; set; }
        public DateTime FromCacheDate { get; set; }
        public object JsonSerializerDesserialize { get; set; }
        public object JsonConvertDeserialize { get; set; }
    }

    public class DateTimeModel
    {
        public DateTime EffectiveDate { get; set; }
    }
}


Startup.cs

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Newtonsoft.Json.Serialization;

namespace memcachedtester
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers()
                .AddNewtonsoftJson(options =>
            {
                options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
                options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
            });

            services.AddEnyimMemcached();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseHttpsRedirection();

            app.UseRouting();

            app.UseAuthorization();

            app.UseEnyimMemcached();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }
    }
}

csproj file

<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>netcoreapp3.1</TargetFramework>
    <UserSecretsId>549e9dd1-7f33-4159-a6a5-19b7982528a8</UserSecretsId>
    <DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="EnyimMemcachedCore" Version="2.4.3" />
    <PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.1.5" />
    <PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.9.10" />
  </ItemGroup>


</Project>

Activity

IcoDeveloper

IcoDeveloper commented on Dec 16, 2023

@IcoDeveloper

That's an issue with the jsonserializer. you need to set an option to keep it from fiddling with timestamps.

var serializer = JsonSerializer.Create(new JsonSerializerSettings()
{
    DateParseHandling = DateParseHandling.None
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @gunmeet@IcoDeveloper

        Issue actions

          Local timezone added when deserializing Model having DateTime property · Issue #145 · cnblogs/EnyimMemcachedCore