I'm following [Getting started with ASP.NET MVC 3][1]. And I can't add/edit with value of Price = 9.99 or 9,99. It said: "The value '9.99' is not valid for Price." and "The field Price must be a number."
How to fix this?
Model:
public class Movie
{
public int ID { get; set; }
public string Title { get; set; }
public DateTime ReleaseDate { get; set; }
public string Genre { get; set; }
public decimal Price { get; set; }
}
public class MovieDbContext : DbContext
{
public DbSet<Movie> Movies { get; set; }
}
Controller:
public class MovieController : Controller
{
private MovieDbContext db = new MovieDbContext();
//
// GET: /Movie/
public ViewResult Index()
{
var movie = from m in db.Movies
where m.ReleaseDate > new DateTime(1984, 6, 1)
select m;
return View(movie.ToList());
}
//
// GET: /Movie/Details/5
public ViewResult Details(int id)
{
Movie movie = db.Movies.Find(id);
return View(movie);
}
//
// GET: /Movie/Create
public ActionResult Create()
{
return View();
}
//
// POST: /Movie/Create
[HttpPost]
public ActionResult Create(Movie movie)
{
if (ModelState.IsValid)
{
db.Movies.Add(movie);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(movie);
}
//
// GET: /Movie/Edit/5
public ActionResult Edit(int id)
{
Movie movie = db.Movies.Find(id);
return View(movie);
}
//
// POST: /Movie/Edit/5
[HttpPost]
public ActionResult Edit(Movie movie)
{
if (ModelState.IsValid)
{
db.Entry(movie).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(movie);
}
//
// GET: /Movie/Delete/5
public ActionResult Delete(int id)
{
Movie movie = db.Movies.Find(id);
return View(movie);
}
//
// POST: /Movie/Delete/5
[HttpPost, ActionName("Delete")]
public ActionResult DeleteConfirmed(int id)
{
Movie movie = db.Movies.Find(id);
db.Movies.Remove(movie);
db.SaveChanges();
return RedirectToAction("Index");
}
protected override void Dispose(bool disposing)
{
db.Dispose();
base.Dispose(disposing);
}
}
}
View:
@model MvcMovies.Models.Movie
@{
ViewBag.Title = "Create";
}
<h2>Create</h2>
<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"> </script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
@using (Html.BeginForm()) {
@Html.ValidationSummary(true)
<fieldset>
<legend>Movie</legend>
<div class="editor-label">
@Html.LabelFor(model => model.Title)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Title)
@Html.ValidationMessageFor(model => model.Title)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.ReleaseDate)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.ReleaseDate)
@Html.ValidationMessageFor(model => model.ReleaseDate)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.Genre)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Genre)
@Html.ValidationMessageFor(model => model.Genre)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.Price)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Price)
@Html.ValidationMessageFor(model => model.Price)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
public DbSet<Movie> Movies { get; set; }
}
I just stumbled on this again after 2 years. I thought ASP.NET MVC 5 had solved this but looks like it's not the case. So here goes how to solve the problem...
Create a class called DecimalModelBinder
like the following and add it to the root of your project for example:
using System;
using System.Globalization;
using System.Web.Mvc;
namespace YourNamespace
{
public class DecimalModelBinder : IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
ValueProviderResult valueResult = bindingContext.ValueProvider
.GetValue(bindingContext.ModelName);
ModelState modelState = new ModelState { Value = valueResult };
object actualValue = null;
if(valueResult.AttemptedValue != string.Empty)
{
try
{
actualValue = Convert.ToDecimal(valueResult.AttemptedValue, CultureInfo.CurrentCulture);
}
catch(FormatException e)
{
modelState.Errors.Add(e);
}
}
bindingContext.ModelState.Add(bindingContext.ModelName, modelState);
return actualValue;
}
}
}
Inside Global.asax.cs,
make use of it in Application_Start()
like this:
ModelBinders.Binders.Add(typeof(decimal?), new DecimalModelBinder());
You are one of the non-English customers, which MS has not foreseen. You will need to put some extra effort into making your version run. I had a similar problem, denying me both "9,99" and "9.99" as valid numbers. It seems like once server-side validation failed, and once client-side validation, causing no number to be accepted.
So you have to make the validation congruent.
Like suggested in the comments, have a look at http://msdn.microsoft.com/en-us/library/gg674880(VS.98).aspx and http://haacked.com/archive/2010/05/10/globalizing-mvc-validation.aspx and MVC 3 jQuery Validation/globalizing of number/decimal field or - should you understand German (or just look at the code examples) http://www.andreas-reiff.de/2012/06/probleme-mit-mvcmovies-beispiel-validierung-des-preises-mit-dezimalstellen-schlagt-fehl/
BTW, same problem exists for both the Music and Movie example tutorials.
I encountered this issue when developing a web application for an English audience, on a Pc in The Netherlands.
A model property of type double, generated this server-side validation error:
The value '1.5' is not valid for .
On an breakpoint, I saw these values in the Immediate Window:
?System.Threading.Thread.CurrentThread.CurrentUICulture
{en-US}
?System.Threading.Thread.CurrentThread.CurrentCulture
{nl-NL}
As a solution (or maybe a work-around), you can specify the globalization settings in the web.config file.
<configuration>
<system.web>
<globalization culture="en" uiCulture="en" />
Of course this means that you force your users to enter numbers in English formatting, but that is just fine, in my case.
In 2019, this problem is still not solved. Using ASP Core 2.1, my UI is in French (decimal separator= ',') and I couldn't get the validation to work anytime I had a decimal number.
I found a workaround, not ideal though: I created a french-based CultureInfo but I changed the decimal separator to be the same as in Invariant Culture : '.'.
This made the trick, my decimal numbers are now displayed US style (but I am ok with it) and validation works.
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
//Culture specific problems
var cultureInfo = new CultureInfo("fr-FR");
cultureInfo.NumberFormat.NumberDecimalSeparator = ".";
System.Threading.Thread.CurrentThread.CurrentUICulture = cultureInfo;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With