Web API can't deserialize a Javascript Date.toISOString()? - c#

I'm looking for a way to pass javascript dates to .NET web api controllers without installing another library on the client...
I'm expecting the javascript dates to deserialize to .NET DateTime.
var date = new Date();
post({currentDate: date.toISOString()});
Arrives at server as a DateTime.Min (indicating it failed to deserialize).
Here's an example of what is being sent over the wire, but the ApiController is not able to create a DateTime with the correct date...
Request:
{"Date":"2014-04-16T17:03:03.383Z"}
C#:
[Serializable]
public class MyObj
{
public DateTime Date { get; set; }
}
public class MyController : ApiController
{
public HttpResponseMessage Post(MyObj dd)
{
// dd's Date property equals DateTime.Min rather than the correct date...
return null;
}
}
}

Remove the [Serializable] attribute.

I think you should push the ticks from the client side. Then the server side will get a date from the ticks.
Example:
Javascipt:
var date = new Date();
post({ticks: date.getTime()});
.NET:
DateTime date = new DateTime(ticks);

Related

Is there a way to change the DateTimeOffset to UtcDateTime or LocalDateTime in Model or Dto definition classes?

I have a .NET 6 Web API using Entity Framework. Some endpoints receive objects containing a datetimeoffset attribute and the incoming values are in the form of local datetime.
The problem is, with the latest version of PostgreSql, datetimeoffset values can only take the datetimeoffset inputs in ...T+00 UTC format. So when my value is something like ...T+03, I'm unable to write that to the database.
This is my model class
public class MyModel : BaseEntity
{
public DateTimeOffset MyDate { get; set; }
}
And this is my dto class
public class Dto : BaseDto
{
public DateTimeOffset MyDate { get; set; }
}
Temporary Solution
For now I change the format every time I post to and get from database in my service class as follows:
For post:
myDto.MyDate = myDto.MyDate.UtcDateTime;
var myModel = _mapper.Map<MyModel>(myDto);
await _unitOfWork.MyModelContext.CreateAsync(myModel);
await _unitOfWork.SaveAsync();
//...
For get:
var myModels = await _unitOfWork.MyModelContext.GetAll();
foreach(var myModel in myModels)
myModel.MyDate = myModel.MyDate.LocalDateTime;
//...
//or
var myModel = await _unitOfWork.MyModelContext.GetById(id);
myModel.MyDate = myModel.MyDate.LocalDateTime;
//...
I know that this is a bad approach. I am wondering if it is possible to make this operation inside my Dtos or Models so that I don't need make this operation on each service.
I am open to other suggestions as well.
You need to create a custom type converter like below.
public class DateTimeOffSetTypeConverter : ITypeConverter<DateTimeOffset, DateTimeOffset>
{
public DateTimeOffset Convert(DateTimeOffset source, DateTimeOffset destination, ResolutionContext context)
{
destination = source.UtcDateTime;
return destination;
}
}
Then define it in your mapping configuration class.
var configuration = new MapperConfiguration(cfg => {
cfg.CreateMap<DateTimeOffset, DateTimeOffset>().ConvertUsing(new DateTimeOffSetTypeConverter());
//your mapping configurations
});

Controller changing date from dd/MM/yyyy to MM/dd/yyyy

I am using .NET Core 3.1 for an API that works like this:
[HttpPost]
public IActionResult Post([FromBody]ClassA classA)...
[HttpGet]
public IActionResult Get([FromQuery]ClassB classB)...
public ClassA {
[JsonProperty("date1")]
public DateTime date {get;set;}
}
public ClassB{
[JsonProperty("date2")]
public DateTime date {get;set;}
}
When I send a GET request I am able to get in the format I want (dd/MM/yyyy) because I have a custom ModelBinder that does the trick.
I thought it would work also for POST request but it does not. When I send a date in format (dd/MM/yyyy), it get as (MM/dd/yyyy) in controller.
I read somewhere that ModelBinder works only for x-www-form-urlencoded, but for my POST method I am sending a JSON.
I have tried changing DefaultThreadCurrentCulture and DefaultThreadCurrentUICulture but it did not work.
I have tried also using a custom JsonConverter but then I would have to add the JsonConverter to every date I have.
I am looking for a more sophisticated solution.
Try following :
public class ClassA
{
private DateTime _date
[JsonProperty("date1")]
public string date {
get{ return _date.ToString("MM/dd/yyyy");}
set{ _date = DateTime.ParseExact(value, "MM/dd/yyyy", System.Globalization.CultureInfo.InvariantCulture);}
}
}

Best way to Pass Typescript Date property as a parameter to a Web Api 2.0 method

I have a date picker in html which is bound to a Date property of an employee.
ex: i have selected the date as "Thu Feb 22 2018 00:00:00 GMT+0530 (India Standard Time)".this is the value i get when i log in console.
But when i tried to debug in C# the value is changed.
{21-02-2018 18:30:00}
How to handle or work with the typescript date object when passing it to a API method and displaying it back
My typescript Model
export class Visitor {
public id: number;
public firstname: string;
public lastname: string;
public dob: Date;
public genderId: number;
public age: number;
}
and C# model
public class Visitor
{
public int Id { get; set; }
public string Lastname { get; set; }
public string Firstname { get; set; }
public int Age { get; set; }
public DateTime DOB { get; set; }
}
As long as you are passing a valid Date object you should be fine.
Your problem probably lies in your Culture settings in .NET side.
Can you please try doing this in your controller action:
var culture = new CultureInfo("gu-IN");
CultureInfo.DefaultThreadCurrentCulture = culture;
CultureInfo.DefaultThreadCurrentUICulture = culture;
Since you provide no code, this is merely a guess.
When you are printing in console, browser is printing the date in local timezone which is India in your case. When you are retrieving the value on server, C# is treating date in UTC. That is why you see a difference of 5.30 hours. India time is UTC + 5.30 Hours.
If you are storing the date value in UTC format on server side then convert the value of date object from client side to UTC using the libraries such as momentjs.
While retrieving the value from server, send the UTC value from server and convert it to local time zone using libraries such as momentjs. I think this strategy will work.

How to make a JSON Post Request and handle it

I would like to make a Json Post Request to my MVC .NET application api beeing: http://localhost:39622/api/holiday
The Json file should represent the following class:
public class Holiday
{
public string ldapName { get; set; }
public DateTime date {get; set;}
}
I have already initialized an instance of my model class within the "postHoliday" method and converted it to a JSON file.
public void postHoliday()
{
Holiday holiday1 = new Holiday();
holiday1.ldapName = "dkassube";
holiday1.date = new DateTime(2016, 08, 01);
string output = JsonConvert.SerializeObject(holiday1);
WebRequest request = WebRequest.Create("localhost:39622/api/holiday");
request.Method = "POST";
// What to do here?
}
I´m not really sure on how to send the JSON to my API controller and how I can handle the request when it arrives. When the API controller receives the JSON i want to convert it back to an instance of Holiday.
public class HolidayController : ApiController
{
public Holiday handleIncomingHoliday()
{
Holiday incomingHoliday = new Holiday();
// What to do here?
return incomingHoliday;
}
}

ASP.NET MVC How to handle dynamic datetime format from database

In my ASP.NET MVC 5 dwith EF 6 project, I have a database where datetime format is stored as string like "dd-MM-yyyy". User can change this format any time. User will use the given format in the date fields in the view. But when they will post that. Automatically it will bind as a DateTime for that property. I am statically handling it by the following code
[DataType(DataType.Time), DisplayFormat(DataFormatString = "{HH:mm}", ApplyFormatInEditMode = true)]
public DateTime? EndingTime { get; set; }
public string EndingTimeValue
{
get
{
return EndingTime.HasValue ? EndingTime.Value.ToString("HH:mm") : string.Empty;
}
set
{
EndingTime = DateTime.Parse(value);
}
}
but I know it's not a best way to do that. There may need a model binder or filter or any kind of custom attribute. I will be greatly helped if you give me a efficient solution with sample code. Thanks in advance.
NB: I am using razor view engine. and my solution consists of 7 projects. So there is no chance of using Session in model. Again I have a base repository class for using entity framework.
People usually store the datetime in the database as a datetime.
Then wherever you do a translation from datetime to string that datetime can be displayed in a format that depends on the culture of the viewer.
By doing this you can quickly make a page with datetime formats that will format the datetimes nicely wherever you are.
change the culture you pass to the toString and the format changes.
please see this MSDN page for more info about it.
edit: (see comments below)
anywhere on server:
string WhatYouWant = yourTime.ToCustomFormat()
and create an extension method for the datetime that gets the format out of the database and returns a string in the correct format.
public static class MyExtensions
{
public static string ToCustomFormat(this DateTime yourTime)
{
// Get the following var out of the database
String format = "MM/dd/yyyy hh:mm:sszzz";
// Converts the local DateTime to a string
// using the custom format string and display.
String result = yourTime.ToString(format);
return result;
}
}
This will allow you to call it anywhere anytime on your server. You can't access the method client side in javascript. I hope this helps.
(To be honest I'm a new developer too and still have a lot to learn ^^)
I have tried many options regarding this problem. Now what I am doing is created an action filter to catch all the DateTime and nullable DateTime Fields. Here I am providing the binder.
public class DateTimeBinder : DefaultModelBinder
{
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
DateTime date;
var displayFormat = SmartSession.DateTimeFormat;
if (DateTime.TryParseExact(value.AttemptedValue, displayFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out date))
{
return date;
}
else
{
bindingContext.ModelState.AddModelError(bindingContext.ModelName,"Invalid Format");
}
return base.BindModel(controllerContext, bindingContext);
}
}
in views the code I am formatting the date using same date format.

Categories