Using DateTimeOffset in a DateTimePicker and Grid
Environment
Product | DateTimePicker for Progress Telerik UI for ASP.NET MVC, Grid for Progress Telerik UI for ASP.NET MVC |
Description
How can I bind a DateTimeOffset
model value to the Telerik UI for ASP.NET MVC DateTimePicker and Data Grid components?
Solution
The DateTimeOffset
structure represents a new date-time data structure that defines a point relative to the UTC time zone. However, neither databases nor JS are able of storing this structure as is because the DateTimeOffset
is serialized as an object. The UI for ASP.NET MVC components that use dates depend on the JavaScript Date type API, which means that they need to work with a JavaScript Date.
The default MVC binder is capable of binding a DateTimeOffset
only if the submitted parameter is in the 2017-04-17T05:04:18.070Z
format. In other words, if the UI for ASP.NET MVC components implement the DateTimeOffset
overload, their use will be limited only to the above format or they will require a custom binder.
To achieve the desired results, map database models with DateTimeOffset
fields to view models with DateTime
fields and use those view models in the Telerik UI for ASP.NET MVC components. AutoMapper is a popular third-party library that can map the models as shown below.
-
Install AutoMapper from NuGet Package Manager or from the package manager console:
PM> Install-Package AutoMapper
Upon a successful installation, the
packages.config
file should include a similar package:<package id="AutoMapper" version="7.0.1" targetFramework="net45" />
-
Add a Mapping profile class that inherits from
AutoMapper.Profile
and list the required mappings.public class MappingProfile : Profile { public MappingProfile() { CreateMap<Car, CarViewModel>(); CreateMap<CarViewModel, Car>(); CreateMap<DateTime, DateTimeOffset>().ConstructUsing(x => new DateTimeOffset(x)); CreateMap<DateTimeOffset, DateTime>(); } }
public class Car { public DateTimeOffset ProductionDate { get; set; } }
public class CarViewModel { public DateTime ProductionDate { get; set; } }
using AutoMapper; public class HomeController : Controller { private readonly IMapper mapper; public HomeController() { if(mapper == null) { var mappingConfig = new MapperConfiguration(mc => { mc.AddProfile(new MappingProfile()); }); mapper = mappingConfig.CreateMapper(); } } // to bind the model to any UI for ASP.NET Date/Time picker in the Index.cshtmls view public ActionResult Index() { return View(mapper.Map<CarViewModel>(cars.FirstOrDefault())); } // to use DateTimeOffset in the context of the Ajax() bound grid public ActionResult AllCars([DataSourceRequest] DataSourceRequest request) { // map the database models to the viewmodels var result = cars.Select(car => mapper.Map<CarViewModel>(car)); // call the ToDataSourceResult() extension method over the mapped collection return Json(result.ToDataSourceResult(request)); } }
For the complete implementation, refer to this GitHub project.