Search code examples
angularasp.net-coreasp.net-core-webapimultipartform-data

ASP.NET Core 6 Web API: "The value string is not valid for DateTime."


I am practicing passing value to a form in Angular, and then put it in a post url in ASP.NET Core.

Here is what I do - this is my component:

export class Demo11CreateDeleteApiComponent implements OnInit {
    form: FormGroup;
    file: any;

    constructor(
        private productApiService: ProductApiService,
        private formBuilder: FormBuilder,
    ){}

    ngOnInit() { 
        this.form = this.formBuilder.group({
            name: '',
            price: 0,
            quantity: 0,
            status: true,
            description: '',
            photo: '',
            categoryId: 1
        })
        
    }

    fileControl(e:any){
        this.file = e.target.files[0];
    }

    submit(){      
        let product: ProductApi = this.form.value;
        
        //=======================
        //Assuming ProductApi is like this:
            ProductApi{
                name: string = "test";
                price: number = 1;
                quantity: number = 1;
                status: boolean = true;
                description: string = "test";
                created: string = "16/02/2023" the format is "dd/MM/yyyy";
                photo: string = "";
                categoryId: number = 1;
            }
        //=======================

        let formData = new FormData();
        formData.append('data', this.file);
        

        for (let k in product) {
            formData.append(`product.${k}`, product[k]);            
        }

        this.productApiService.createWithFile(formData).then(
            res => {
                this.result = do something;
            },
            err => {
                console.log(err);                
            }
        )
    }

}

And the createWithFile method looks like this:

async createWithFile(file: FormData){
    return await lastValueFrom(this.httpClient.post(this.baseUrl+'create-with-file', file));
}

Now in ASP.NET Core 6, my product class is:

public partial class Product
{
    public int Id { get; set; }

    [Required(ErrorMessage = "Invalid data, must be a non-empty string")]
    public string? Name { get; set; }

    [Required(ErrorMessage = "Invalid data, must be an integer")]
    public int? Quantity { get; set; }

    public string? Description { get; set; }

    [Required(ErrorMessage = "Invalid data, must be a double")]
    public double? Price { get; set; }    

    public bool Status { get; set; }    

    public string? Photo { get; set; }

    public DateTime Created { get; set; }  

    public int CategoryId { get; set; }
}

And here is the controller:

[HttpPost("create-with-file")]
[Produces("application/json")]
public IActionResult CreateWithFile(Product product, IFormFile data)
{
    try
    {
        if (ModelState.IsValid)
        {
            return Ok();
        }
        return BadRequest(ModelState);
    }
    catch
    {
        return BadRequest();
    }
}

What I expect is, the product from ASP.NET Core will take all values from Angular with no problem, but instead, I get this error:

product.Created: ["The value '16/02/2023' is not valid for Created."]

That means ModelState returned false because the Created method field. I look for many answers in SOF but no answer solved my problem, I even do this but it doesn't work either:

[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:dd-MM-yyyy}", ApplyFormatInEditMode = true)]
public DateTime Created { get; set; }

I've kinda reached a dead end, please help :(


Solution

  • As mentioned in the comment, you should pass the date as ISO 8601 format instead of "dd/MM/yyyy" so that the API side will receive the date correctly.

    With Date.prototype.toISOString()

    let now = new Date();
    
    // To remove time from date
    let created = new Date(now.getFullYear(), now.getMonth(), now.getDate()).toISOString();  
    // 2023-02-16T16:00:00.000Z
    product.created = created;
    

    Note that the ISO String will be in the UTC offset.