Search code examples
c#asp.net-mvcasp.net-corerazor

Using ASP.NET Core MVC with .NET 6, number from input tag in a form is losing the decimal separator when being transferred to the controller


I was trying to create a form to add new items to my database, and my model includes a price. The type of the price is double, and the number input on my form has a step of .01 The issue is that when submitting my new item with the form, the number is losing the decimal separator, regardless of the lang attribute of the input tag, and so using a comma or dot doesn't make a difference. Because of this, 5.45 and 5,45 will both turn into 545.00 when written as a price on my item's list.

Here's my model:

public class Pizza 
{
    public Pizza(int id, string name, string description, double price, string pictureUrl) 
    {
        Id = id;
        Name = name;
        Description = description;
        Price = price;
        PictureUrl = pictureUrl;
    }

    public Pizza() { }

    [Key]
    public int Id { get; set; }
    
    [Required(ErrorMessage = "Il campo è obbligatorio.")]
    public string Name { get; set; }
    
    [Required(ErrorMessage = "Il campo è obbligatorio.")]
    public string Description { get; set; }
    
    [Required(ErrorMessage = "Il campo è obbligatorio.")]
    [Range(0, double.MaxValue, ErrorMessage = "Il prezzo non può essere negativo.")]
    public double Price { get; set; } // This is the property which is being set to the wrong value
    
    [Required(ErrorMessage = "Il campo è obbligatorio.")]
    public string PictureUrl { get; set; }
}

And here's the code for my controller's action:

[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult New(Pizza pizza) 
{
    if (!ModelState.IsValid) 
    {
        return View("New", pizza);
    }

    using (var db = new PizzasDbContext()) 
    {
        int modifications = db.AddPizza(pizza);
        Console.WriteLine(modifications);
    }

    return RedirectToAction("Index");
}

Solution

  • Found a somewhat hacky solution that works for me. The issue is that the form on my view would always, at all times, return the decimal value with a dot. This is most likely a standard of HTML or JavaScript.

    The solution was to force the server's thread to use a culture that uses a dot instead of a comma to represent doubles, as the value returned from the view is actually a string, and therefore when parsed would lose any dot or useless zeroes.

    The code that worked for me is the following:

    var cultureInfo = new CultureInfo("en-US");
    cultureInfo.NumberFormat.CurrencySymbol = "€";
    cultureInfo.NumberFormat.NumberDecimalSeparator = ".";
    
    CultureInfo.DefaultThreadCurrentCulture = cultureInfo;
    CultureInfo.DefaultThreadCurrentUICulture = cultureInfo;
    

    I found the code on this StackOverflow post.