2

I'm having difficulties on sending the value of DateOnly & TimeOnly in .Net 6 to database.

I have read multiple answers here on this issue, and have tried it all but its still showing error 400

heres the converter I made

 public class DateOnlyJsonConverter : JsonConverter<DateOnly>
    {
      
        public override DateOnly Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
        {
            var value = reader.GetString();

            return DateOnly.Parse(value!);
        }

        public override void Write(Utf8JsonWriter writer, DateOnly value, JsonSerializerOptions options)
        {
            writer.WriteStringValue(value.ToString("yyyy-MM-dd"));
        }

for the TimeOnly

public class TimeOnlyJsonConverter : JsonConverter<TimeOnly>
    {
        public override TimeOnly Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
        {
            var value = reader.GetString();

            return TimeOnly.Parse(value!); 
        }

        public override void Write(Utf8JsonWriter writer, TimeOnly value, JsonSerializerOptions options)
        {
            writer.WriteStringValue(value.ToString("HH:mm:ss.fff"));
        }
    }

I have also added this on the program.cs

builder.Services.AddControllers().AddJsonOptions(
    options =>
    {
        options.JsonSerializerOptions.Converters.Add(new DateOnlyJsonConverter());
        options.JsonSerializerOptions.Converters.Add(new TimeOnlyJsonConverter());
    }

and this is the code on the controller

    [HttpPost]
            public async Task<IActionResult> CheckIn(Absensi request)
            {
                 var absensis = new Absensi()
                {
                    IDKaryawan = request.IDKaryawan,
                    NamaKaryawan = request.NamaKaryawan,
                    IDPerusahaan = request.IDKaryawan,
                    NamaPerusahaan = request.NamaKaryawan,
                     Tanggal = DateOnly.FromDateTime(DateTime.Now),
                    WaktuCheckIn = TimeOnly.FromDateTime(DateTime.Now),
                   // WaktuCheckOut = TimeOnly.FromDateTime(DateTime.Now),
                 };
                await _context.Absensis.AddAsync(absensis);
                await _context.SaveChangesAsync();
                return Ok("Absensi Created!");
            }

yet, when its still showing error 400 when executed thru swagger

{ 
 "type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
 "title": "One or more validation errors occurred.",
 "status": 400,
 "traceId": "00-6756849f7366cabf4b0d7d8289fc4173-53ac44cc08885df5-00",
 "errors": {
        "request": [
        "The request field is required."
       ],
"$.tanggal": [
  "The JSON value could not be converted to System.DateOnly. Path: $.tanggal | LineNumber: 5 | BytePositionInLine: 14."
  ]
 }
}

error 400 swagger

edit : to add absensi class & json

public partial class Absensi
    {
        public string IDKaryawan { get; set; } = null!;
        public string NamaKaryawan { get; set; } = null!;
        public string IDPerusahaan { get; set; } = null!;
        public string NamaPerusahaan { get; set; } = null!;
        [JsonConverter(typeof(DateOnlyJsonConverter))] 
        public DateOnly? Tanggal { get; set; }
        [JsonConverter(typeof(TimeOnlyJsonConverter))]
        public TimeOnly? WaktuCheckIn { get; set; }
        [JsonConverter(typeof(TimeOnlyJsonConverter))]
        public TimeOnly? WaktuCheckOut { get; set; } 
        public int Id { get; set; }

    }
}

json

"tanggal": {
    "year": 0,
    "month": 0,
    "day": 0,
    "dayOfWeek": 0
  },
  "waktuCheckIn": {
    "hour": 0,
    "minute": 0,
    "second": 0,
    "millisecond": 0,
    "ticks": 0
  },
  "waktuCheckOut": {
    "hour": 0,
    "minute": 0,
    "second": 0,
    "millisecond": 0,
    "ticks": 0
  },

Please let me know what i have done and how to fix it. thank you

S S
  • 19
  • 3
  • If I'm not mistaken you need to modify `Absensi` type and add an attribute to specify that the `DateOnly` property is going to be parsed using your converters – Pablo Recalde Jan 11 '23 at 08:30
  • @PabloRecalde do you mean on the Absensi model, or the db context? and if you could please direct me on how to do that i would be grateful, because i havent found anything on that. please and thank you. – S S Jan 11 '23 at 08:38
  • Try changing `DateOnly.Parse(value!)` to `DateOnly.ParseExact(value!, "yyyy-MM-dd")`. Also please provide request you are trying to post and the `Absensi` class. – Guru Stron Jan 11 '23 at 10:54
  • Can you post your JSON or the relevant snippet? – SBFrancies Jan 11 '23 at 16:04
  • @SBFrancies sorry for the late reply. i just got online. i edited the post to include the json for the dateonly and time only – S S Jan 12 '23 at 12:17
  • @GuruStron sorry for the late reply. i tried with that yesterday before posting here and it didnt work. added the Absensi class as well – S S Jan 12 '23 at 12:18
  • 1
    Your converters expect that TimeOnly/DateOnly are specified as a (formatted) string value in JSON (like `{ "tanggal": "2022-01-31" }`), but your actual JSON does contain those values "destructured" as JSON objects (all members separately). – Christian.K Jan 12 '23 at 12:23
  • @Christian.K thank you, how do i fix it please? because in the code im taking the value of date from datetime.now. which i thought it would automatically in yyyy-mm-dd – S S Jan 12 '23 at 13:43
  • 1
    How are you generating your JSON - or is it provided to you? – SBFrancies Jan 12 '23 at 14:06
  • @SBFrancies the provided one directly, i never change anything of the JSON, just automatic from the codes. – S S Jan 12 '23 at 15:34
  • @SBFrancies right the only way im countering it by creating 3 separate columns on sql, which converts the value of datetime from Tanggal, WaktuCheckIn, WaktuCheckout to dateonly and timeonly. then call those values back thru GET method, which works without issue but definitely not an efficient one. – S S Jan 12 '23 at 15:38

1 Answers1

1

I think you're missing the attribute that tells the Json parser to use your specific converter for that property.

On the Absensi type, you need to decorate the property of type DateOnly like this:

public class Absensi 
{
    [JsonConverter(typeof(DateOnlyJsonConverter))]
    public DateOnly MyDateOnlyProperty { get; set; }
    ...
}
Pablo Recalde
  • 3,334
  • 1
  • 22
  • 47