C
C#2y ago
Utsuhoagie

✅ Nullable DateTimeOffset field in a [FromForm] model is always null

I have a React Native (Expo running on Expo Go on an Android specifically) client and an ASP.NET Core Web API server. My client sends requests with content type multipart/form-data, and supplies the correct values for each field. Specifically in this example, the BirthDate field is either omitted entirely from the FormData, or it's given an ISO timestamp string with Z offset. I don't send null, undefined, '' or anything like that. But when the request reaches the server, the model's nullable BirthDate field is always null with either cases (client doesn't include the field in its FormData, OR the field's value is something like 2023-04-27T02:50:23.636Z). Other fields are still sent properly (either given a proper value, or is null once the server reads the request).
public class UpdateSelfRequest
{
public string NationalId { get; set; } = string.Empty;
public string? Phone { get; set; }
public string? Address { get; set; }
public DateTimeOffset? BirthDate { get; set; }
public IFormFile? Image { get; set; }
}

[HttpPut("UpdateSelf/{NationalId}")]
[Authorize(Roles = AuthRoles.Employee)]
[Consumes("multipart/form-data")]
public async Task<IActionResult> UpdateSelf(
[FromRoute] string NationalId,
[FromForm] UpdateSelfRequest req)
{
// -----> Here, req.BirthDate is null despite the client sending a value
var result = await _service.UpdateSelf(NationalId, req);
if (!result.Success)
{
return Forbid();
}

return Ok();
}
public class UpdateSelfRequest
{
public string NationalId { get; set; } = string.Empty;
public string? Phone { get; set; }
public string? Address { get; set; }
public DateTimeOffset? BirthDate { get; set; }
public IFormFile? Image { get; set; }
}

[HttpPut("UpdateSelf/{NationalId}")]
[Authorize(Roles = AuthRoles.Employee)]
[Consumes("multipart/form-data")]
public async Task<IActionResult> UpdateSelf(
[FromRoute] string NationalId,
[FromForm] UpdateSelfRequest req)
{
// -----> Here, req.BirthDate is null despite the client sending a value
var result = await _service.UpdateSelf(NationalId, req);
if (!result.Success)
{
return Forbid();
}

return Ok();
}
Logs in screenshot:
12 Replies
JakenVeina
JakenVeina2y ago
definitely need to have a look at one of your requests
Utsuhoagie
UtsuhoagieOP2y ago
// NationalId, Address, Phone, BirthDate are all strings. BirthDate is possibly undefined.
const formData = new FormData();
formData.append('NationalId', NationalId);
formData.append('Address', Address);
formData.append('Phone', Phone);
if (BirthDate) {
formData.append('BirthDate', BirthDate);
}
if (Image) {
formData.append('Image', Image);
}

const res = await axios.put(
`Employees/UpdateSelf/${NationalId}`,
formData,
{ headers: { 'Content-Type': 'multipart/form-data' } }
);
// NationalId, Address, Phone, BirthDate are all strings. BirthDate is possibly undefined.
const formData = new FormData();
formData.append('NationalId', NationalId);
formData.append('Address', Address);
formData.append('Phone', Phone);
if (BirthDate) {
formData.append('BirthDate', BirthDate);
}
if (Image) {
formData.append('Image', Image);
}

const res = await axios.put(
`Employees/UpdateSelf/${NationalId}`,
formData,
{ headers: { 'Content-Type': 'multipart/form-data' } }
);
This?
JakenVeina
JakenVeina2y ago
no, like the actual request that certainly LOOKS fine, but it doesn't prove much of anything
Utsuhoagie
UtsuhoagieOP2y ago
It looks pretty normal to me, I tried checking the Network inspector in Expo Go and it does contain an actual timestamp for BirthDate
JakenVeina
JakenVeina2y ago
does that not suggest it's your client code not encoding it properly?
Utsuhoagie
UtsuhoagieOP2y ago
How do I check that? Closest I could try is this Network inspector in Expo Go:
Utsuhoagie
UtsuhoagieOP2y ago
Utsuhoagie
UtsuhoagieOP2y ago
SOLVED (Kind of) I was dumb, and maybe the Network inspector lied to me. What I was trying to append() to was actually a Date object, not an ISO timestamp string. I just used the wrong explicit type in TypeScript (fix BirthDate?: string to BirthDate?: Date, because a date picker component was changing BirthDate into a Date), so it was trying to append a Date instead, and while the Network inspector still shows an ISO string (like the screenshot above), my server can't bind the property at all. Fixing the types worked, even though the Network inspector still shows the same data being sent.
JakenVeina
JakenVeina2y ago
that'll do it Developer Tools? F12?
Utsuhoagie
UtsuhoagieOP2y ago
This is on React Native on a physical phone though (specifically it's an Expo app, running on Expo Go on an Android). The only "devtools" I have are in the screenshot which is pretty primitive (there used to be a debugger app for older versions but I can't get it to run on my current version)
JakenVeina
JakenVeina2y ago
ah well, that sucks
Accord
Accord2y ago
Was this issue resolved? If so, run /close - otherwise I will mark this as stale and this post will be archived until there is new activity.
Want results from more Discord servers?
Add your server