ASP.NET Core 7 Web API : date serialization for Angular form control

97 views Asked by At

In the Person class, Birthday is defined as DateTime.

public class Person
{
    public string Name { get; set; }
    public DateTime Birthday { get; set; }
}

In my controller, I have an endpoint as follows:

[HttpGet("personId")]
public async Task<ActionResult<Person>> GetPerson(int personId) 
{
    var person = new Person 
                     {
                         Name = "Joe Blow",
                         Birthday = DateTime.Now
                     };
  
    return Ok(person);
}

When I hit my endpoint via Postman, I get this:

{
    "name": "Joe Blow",
    "birthday": "2023-08-07T07:37:17"
}

Okay, awesome. DateTime get serialized into this format. I believe it's called ISO 8601 but it really doesn't matter to me.

What matters is when I put it into a Reactive Forms FormControl, it is seen as a Javascript Date, not a string.

If I first replace it as a JS Date, it works:

person.birthday = new Date(person.birthday);

But I really hate doing that. What am I missing here?

The really annoying part is that in my Angular code, I explicitly state that Person.birthday is a Date:

export class Person {
    name: string;
    birthday: Date;
}

So when I use the HTTP client to get a person:

this.httpClient.get<Person>(url).pipe(take(1)).subscribe(
  {
    next: (result: Person) => {
      console.log('Surpise: result.birthday is a string!');
    }
  }  
);
1

There are 1 answers

3
Eliseo On

You didn't miss anything: A Date from an API always comes back as a string (I think that can not come back as a JavaScript object).

Personally I solved it, By making a simple "map" in my service. In this way, your angular component works always on a Date JavaScript object

getData()
{
    return this.getUrl(...).pipe(map(res:any[])=>{
       res.forEach(x=>{
          x.propertyDate=new Date(x.propertyDate)
       })
       return res;
    }
    )
}

getDataId(int id)
{
    return this.getUrl(...).pipe(map(res:any)=>{
      res.propertyDate=new Date(res.propertyDate)
      return res;
    })
}

saveData(data:any)
{
     const dataSend:any={...data} //make a copy to not transform the origina data
     dataSend.propertyDate=data.propertyDate.ToString()
     return http.post(....,dataSend)
}