web-dev-qa-db-de.com

fehler mit Dezimalzahl in mvc3 - der Wert ist für das Feld nicht gültig

Ich verfolge [Erste Schritte mit ASP.NET MVC 3] [1]. Und ich kann nicht mit dem Wert Preis = 9,99 oder 9,99 hinzufügen/bearbeiten. Es sagte: "Der Wert" 9.99 "ist für den Preis nicht gültig." und "Das Feld Preis muss eine Zahl sein."

Wie kann ich das beheben?

Modell:

    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);
    }
}
}

Aussicht:

    @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; }
}
26
furyfish

Ich bin gerade nach 2 Jahren wieder darauf gestoßen. Ich dachte, ASP.NET MVC 5 hätte dieses Problem gelöst, sieht aber so aus, als wäre es nicht der Fall. Also hier geht es darum, das Problem zu lösen ...

Erstellen Sie eine Klasse mit dem Namen DecimalModelBinder wie folgt und fügen Sie sie beispielsweise dem Stamm Ihres Projekts hinzu:

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;
        }
    }
}

Innerhalb von Global.asax.cs, verwenden Sie es in Application_Start() wie folgt:

ModelBinders.Binders.Add(typeof(decimal?), new DecimalModelBinder());
34

Sie gehören zu den nicht-englischen Kunden, die MS nicht vorgesehen hat. Sie müssen sich mehr Mühe geben, um Ihre Version zum Laufen zu bringen. Ich hatte ein ähnliches Problem und verweigerte mir sowohl "9,99" als auch "9,99" als gültige Nummern. Es scheint, als sei die serverseitige Validierung fehlgeschlagen und einmal die clientseitige Validierung, sodass keine Nummer akzeptiert wird.

Also müssen Sie die Validierung kongruent machen.

Wie in den Kommentaren vorgeschlagen, werfen Sie einen Blick auf http://msdn.Microsoft.com/en-us/library/gg674880(VS.98).aspx Und http://haacked.com/archive/2010/05/10/globalizing-mvc-validation.aspx und MVC 3 jQuery Validierung/Globalisierung von Zahlen-/Dezimalfeld oder - sollten Sie Deutsch verstehen (oder einfach nur die Codebeispiele sehen) http://www.andreas-reiff.de/2012/06/probleme-mit-mvcmovies-beispiel-validierung-des-preises- mit-dezimalstellen-schlagt-fehl/

Übrigens, das gleiche Problem besteht sowohl für die Music- als auch für die Movie-Beispiel-Tutorials.

6
Andreas Reiff

Dieses Problem ist mir bei der Entwicklung einer Webanwendung für ein englisches Publikum auf einem PC in den Niederlanden aufgetreten. 

Eine Modelleigenschaft des Typs double hat diesen serverseitigen Validierungsfehler generiert: 

Der Wert '1.5' ist nicht gültig für.

An einem Haltepunkt sah ich diese Werte im Direktfenster :

?System.Threading.Thread.CurrentThread.CurrentUICulture

{en-US}

?System.Threading.Thread.CurrentThread.CurrentCulture

{nl-NL}

Als Lösung (oder möglicherweise als Problemumgehung) können Sie die Globalisierungseinstellungen in der Datei web.config angeben.

<configuration>
  <system.web>
    <globalization culture="en" uiCulture="en" />

Das bedeutet natürlich, dass Sie Ihre Benutzer dazu zwingen, Zahlen in englischer Formatierung einzugeben. In meinem Fall ist das jedoch in Ordnung.

2
R. Schreurs

Ich habe den Code von Leniel Macaferi ein wenig angepasst, damit Sie ihn für jeden Typ verwenden können:

public class RequestModelBinder<TBinding> : 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
            {
                // values really should be invariant
                actualValue = Convert.ChangeType(valueResult.AttemptedValue, typeof(TBinding), CultureInfo.CurrentCulture);
            }
            catch (FormatException e)
            {
                modelState.Errors.Add(e);
            }
        }

        bindingContext.ModelState.Add(bindingContext.ModelName, modelState);

        return actualValue;
    }
}
1
BineG

Ich habe dieses Problem durch Deaktivieren von Jquery für den Preis gelöst und nur auf der Serverseite für diese Eingabe validiert. Ich habe die Antwort hier gefunden: ASP .NET MVC-Deaktivierung der clientseitigen Validierung auf Feldebene

<div class="col-md-10">
                @{ Html.EnableClientValidation(false); }
                @Html.EditorFor(model => model.DecimalValue, new { htmlAttributes = new { @class = "form-control" } })
                @{ Html.EnableClientValidation(true); }
                @Html.ValidationMessageFor(model => model.DecimalValue, "", new { @class = "text-danger" })
            </div>
1
JohanH

Ich habe versucht, @Leniel Macaferi , aber es hat bei mir nicht funktioniert.

ModelState.IsValid akzeptierte keine Zahlen im Format 7.000,00 

Das Problem begann, als ich den Eigenschaftstyp geändert habe:

[Column("PRICE")]
public decimal Price { get; set; }

zu

[Column("PRICE")]
public decimal? Price { get; set; }

Ich habe auch versucht, die Globalisierung in die web.config aufzunehmen, die ich vergessen hatte

<globalization culture="pt-BR" uiCulture="pt-BR" enableClientBasedCulture="true" />

Die einzige Problemumgehung bestand darin, die Eigenschaft nur in Dezimalzahl zu ändern:

[Column("PRICE")]
public decimal Price { get; set; }

und hat auch die Tabellenspalte so geändert, dass sie KEINE Werte akzeptiert

Ich hoffe es hilft jemandem.

1
Rafael Araújo

Im Jahr 2019 ist dieses Problem immer noch nicht gelöst. Wenn ich ASP Core 2.1) verwende, ist meine Benutzeroberfläche in Französisch (Dezimaltrennzeichen = ',') und ich konnte die Validierung nicht immer zum Laufen bringen, wenn ich eine Dezimalzahl hatte.

Ich habe eine Problemumgehung gefunden, die jedoch nicht ideal ist: Ich habe ein CultureInfo auf Französisch erstellt, aber das Dezimaltrennzeichen wurde so geändert, dass es mit dem in Invariant Culture übereinstimmt: '.'.

Dies hat den Trick gemacht, meine Dezimalzahlen werden jetzt im US-Stil angezeigt (aber ich bin damit einverstanden) und die Validierung funktioniert.

    // 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;

    }
0
XavierAM