Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Local timezone added when deserializing Model having DateTime property #145

Open
gunmeet opened this issue Jun 29, 2020 · 1 comment
Open

Comments

@gunmeet
Copy link

gunmeet commented Jun 29, 2020

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>

@IcoDeveloper
Copy link

IcoDeveloper commented Dec 16, 2023

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
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants