{"id":4353,"date":"2020-12-04T15:43:43","date_gmt":"2020-12-04T14:43:43","guid":{"rendered":"https:\/\/solidt.eu\/site\/?p=4353"},"modified":"2026-01-12T11:16:37","modified_gmt":"2026-01-12T10:16:37","slug":"c-webapi-entity-frameworkjson-utc-time-mapping","status":"publish","type":"post","link":"https:\/\/solidt.eu\/site\/c-webapi-entity-frameworkjson-utc-time-mapping\/","title":{"rendered":"C# WebAPI Entity framework+ModelBinding+JSON UTC-time mapping"},"content":{"rendered":"\n<div style=\"height: 250px; position:relative; margin-bottom: 50px;\" class=\"wp-block-simple-code-block-ace\"><pre class=\"wp-block-simple-code-block-ace\" style=\"position:absolute;top:0;right:0;bottom:0;left:0\" data-mode=\"csharp\" data-theme=\"monokai\" data-fontsize=\"14\" data-lines=\"Infinity\" data-showlines=\"true\" data-copy=\"false\">using System;\nusing System.Linq;\nusing EfDataAdapter.Extensions;\nusing Microsoft.EntityFrameworkCore;\nusing Microsoft.EntityFrameworkCore.Storage.ValueConversion;\n\nnamespace EfDataAdapter\n{\n    public class ApplicationDbContext : DbContext\n    {\n        public ApplicationDbContext(DbContextOptions options) : base(options)\n        {\n        }\n\n        protected override void OnModelCreating(ModelBuilder modelBuilder)\n        {\n            modelBuilder.UseEntityTypeConfiguration();\n            ApplyUtcDateTimeConverter(modelBuilder);\n            base.OnModelCreating(modelBuilder);\n        }\n        private static void ApplyUtcDateTimeConverter(ModelBuilder modelBuilder)\n        {\n            var dateTimeConverter = new ValueConverter&lt;DateTime, DateTime>(v => v.ToUniversalTime(), v => DateTime.SpecifyKind(v, DateTimeKind.Utc));\n            var dateTimeNullableConverter = new ValueConverter&lt;DateTime?, DateTime?>(v => v.HasValue ? v.Value.ToUniversalTime() : (DateTime?)null, v => v.HasValue ? DateTime.SpecifyKind(v.Value, DateTimeKind.Utc) : (DateTime?)null);\n            foreach (var entityType in modelBuilder.Model.GetEntityTypes())\n            {\n                var properties = entityType.ClrType.GetProperties().Where(p => p.PropertyType == typeof(DateTime));\n                foreach (var property in properties)\n                {\n                    modelBuilder.Entity(entityType.Name).Property(property.Name)\n                        .HasConversion(dateTimeConverter);\n                }\n                properties = entityType.ClrType.GetProperties().Where(p => p.PropertyType == typeof(DateTime?));\n\n                foreach (var property in properties)\n                {\n                    modelBuilder.Entity(entityType.Name).Property(property.Name)\n                        .HasConversion(dateTimeNullableConverter);\n                }\n            }\n        }\n    }\n}\n\n\n\/\/\/\/\/\/\/\/\/\/\/\/\/ Edit Api ModelBinding to ensure UTC by default\npublic class UtcDateTimeModelBinder : IModelBinder\n{\n    public Task BindModelAsync(ModelBindingContext bindingContext)\n    {\n        var value = bindingContext.ValueProvider\n                                  .GetValue(bindingContext.ModelName)\n                                  .FirstValue;\n\n        \/\/ Geen waarde meegegeven\n        if (string.IsNullOrWhiteSpace(value))\n        {\n            bindingContext.Result = ModelBindingResult.Success(null);\n            return Task.CompletedTask;\n        }\n\n        if (DateTime.TryParse(value, out var date))\n        {\n            bindingContext.Result = ModelBindingResult.Success(DateTimeHelper.EnsureUtcDefaultUtc(date));\n        }\n        return Task.CompletedTask;\n    }\n}\n\npublic class UtcDateTimeModelBinderProvider : IModelBinderProvider\n{\n    public IModelBinder? GetBinder(ModelBinderProviderContext context)\n    {\n        var type = context.Metadata.ModelType;\n\n        if (type == typeof(DateTime) || type == typeof(DateTime?))\n        {\n            return new UtcDateTimeModelBinder();\n        }\n\n        return null;\n    }\n}\n\n\/\/\/\/\/\/\/\/\/\/\/\/\/\nusing Newtonsoft.Json.Serialization;\nnamespace WebApi\n{\n    public class Startup\n    {\n        public void ConfigureServices(IServiceCollection services)\n        {\n            services.AddControllers(config =>\n            {\n                config.ModelBinderProviders.Insert(0, new UtcDateTimeModelBinderProvider());\n            })\n            .AddNewtonsoftJson(options =>\n            {\n                options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();\n                options.SerializerSettings.DateTimeZoneHandling = Newtonsoft.Json.DateTimeZoneHandling.Utc;\n            });\n        }\n    }\n}<\/pre><\/div>\n","protected":false},"excerpt":{"rendered":"","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"inline_featured_image":false,"footnotes":""},"categories":[6,4,1],"tags":[],"class_list":["post-4353","post","type-post","status-publish","format-standard","hentry","category-dotnet","category-programming","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/solidt.eu\/site\/wp-json\/wp\/v2\/posts\/4353","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/solidt.eu\/site\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/solidt.eu\/site\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/solidt.eu\/site\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/solidt.eu\/site\/wp-json\/wp\/v2\/comments?post=4353"}],"version-history":[{"count":3,"href":"https:\/\/solidt.eu\/site\/wp-json\/wp\/v2\/posts\/4353\/revisions"}],"predecessor-version":[{"id":10032,"href":"https:\/\/solidt.eu\/site\/wp-json\/wp\/v2\/posts\/4353\/revisions\/10032"}],"wp:attachment":[{"href":"https:\/\/solidt.eu\/site\/wp-json\/wp\/v2\/media?parent=4353"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/solidt.eu\/site\/wp-json\/wp\/v2\/categories?post=4353"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/solidt.eu\/site\/wp-json\/wp\/v2\/tags?post=4353"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}