31

[ASP.NETMVC3入門][1]をフォローしています。また、Price=9.99または9,99の値で追加/編集することはできません。「値「9.99」は価格には無効です。」および「フィールド価格は数値でなければなりません。」

これを修正する方法は?

モデル:

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

コントローラ:

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

意見:

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

10 に答える 10

41

私は2年後に再びこれに遭遇しました。ASP.NET MVC 5はこれを解決したと思いましたが、そうではないようです。だからここに問題を解決する方法があります...

次のようなクラスを作成しDecimalModelBinder、プロジェクトのルートに追加します。例:

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

内部では、次のようGlobal.asax.cs,に使用します。Application_Start()

ModelBinders.Binders.Add(typeof(decimal?), new DecimalModelBinder());
于 2013-10-12T21:35:03.743 に答える
7

あなたは英語以外の顧客の1人であり、MSはこれを予測していません。バージョンを実行するには、さらに努力する必要があります。同様の問題が発生し、「9,99」と「9.99」の両方を有効な数値として拒否しました。サーバー側の検証が失敗した後、クライアント側の検証が失敗したため、番号が受け入れられなくなったようです。

したがって、検証を合同にする必要があります。

コメントで提案されているように、 http://msdn.microsoft.com/en-us/library/gg674880(VS.98).aspx および http://haacked.com/archive/2010/05/10をご覧ください。 /globalizing-mvc-validation.aspx および MVC3jQuery検証/数値/小数フィールドのグローバル化 または-ドイツ語を理解している必要があります(またはコード例を参照してください) http://www.andreas-reiff.de/2012/06 / problem-mit-mvcmovies-beispiel-validierung-des-preises-mit-dezimalstellen-schlagt-fehl /

ところで、音楽と映画のサンプルチュートリアルの両方に同じ問題が存在します。

于 2012-08-06T09:13:24.010 に答える
4

この問題は、オランダのPCで英語の視聴者向けのWebアプリケーションを開発しているときに発生しました。

タイプdoubleのモデルプロパティは、次のサーバー側検証エラーを生成しました。

値「1.5」はに対して無効です。

ブレークポイントで、イミディエイトウィンドウに次の値が表示されました。

?System.Threading.Thread.CurrentThread.CurrentUICulture

{en-US}

?System.Threading.Thread.CurrentThread.CurrentCulture

{nl-NL}

解決策(または回避策)として、web.configファイルでグローバリゼーション設定を指定できます。

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

もちろん、これはユーザーに英語形式で数字を入力するように強制することを意味しますが、私の場合はそれで問題ありません。

于 2017-02-03T13:12:18.437 に答える
4

2019年でも、この問題はまだ解決されていません。ASP Core 2.1を使用すると、UIはフランス語(小数点記号='、')であり、10進数がある場合は常に検証を機能させることができませんでした。

回避策を見つけましたが、理想的ではありません。フランス語ベースのCultureInfoを作成しましたが、小数点記号をInvariant Culture:'。'と同じに変更しました。

これでうまくいきました。私の10進数はUSスタイルで表示され(ただし、問題ありません)、検証は機能します。

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

    }
于 2019-07-11T21:33:36.370 に答える
1

Leniel Macaferiのコードを少し変更して、どのタイプにも使用できるようにしました。

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;
    }
}
于 2016-08-19T12:27:42.907 に答える
1

@Leniel Macaferiを試しましたが、うまくいきませんでした。

ModelState.IsValidは、7.000,00のような形式の数値を受け入れませんでした

プロパティタイプを次のように変更すると、問題が発生しました。

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

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

また、忘れていたグローバリゼーションをweb.configに含めようとしました

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

動作した唯一の回避策は、プロパティを10進数のみに戻すことでした。

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

また、テーブルの列をnull値を受け入れないように変更しました

それが誰かを助けることを願っています。

于 2017-03-03T18:01:38.600 に答える
0

あなたは付け加えられます:

protected void Application_BeginRequest()
{
    var currentCulture = (CultureInfo)CultureInfo.CurrentCulture.Clone();
    currentCulture.NumberFormat.NumberDecimalSeparator = ".";
    currentCulture.NumberFormat.NumberGroupSeparator = " ";
    currentCulture.NumberFormat.CurrencyDecimalSeparator = ".";

    Thread.CurrentThread.CurrentCulture = currentCulture;
    //Thread.CurrentThread.CurrentUICulture = currentCulture;
}

To Global.asax(MVC 5.1でテスト済み)。UICultureを変更しなくても機能します。

于 2015-12-23T20:23:51.550 に答える
0

価格に対してjqueryを無効にし、その入力についてサーバー側でのみ検証することで、この問題を解決しました。ここで答えを見つけました: ASP.NETMVCフィールドごとのレベルでクライアント側の検証を無効にする

<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>
于 2016-05-10T10:03:19.233 に答える
0

これは、Leniel Maccaferriソリューションの拡張であり、サーバーとは異なるカルチャ形式での10進値のユーザーエージェントによる送信に関連する問題を回避します。その制限は、値内の唯一の区切り文字である場合に誤ったバインドを発生させる可能性がある数千の区切り文字の解析にバインドされています。

/// <summary>
/// custom decimal model binder
/// </summary>
/// <author>https://stackoverflow.com/users/114029/leniel-maccaferri</author>
/// <see cref="https://stackoverflow.com/a/19339424/3762855"/>
/// <remarks>Integrated with a fix for the decimal separator issue.
/// <para>This issue maybe depends from browsers interpretation of decimal values posted-back to the server when they receive response without any http content-language specific indication.</para>
/// <para>Important! decimal values caming from UI must not be formatted with thousands separator.</para>
/// </remarks>
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
            {
                var culture = Thread.CurrentThread.CurrentCulture;

                //This is needed to convert in the right manner decimal values coming from UI, as seems they always represent the decimal separator as a period("."). 
                //Maybe depends from browsers interpretation of decimal values posted-back to the server when they receive response without any http content-language specific indication.
                if (culture.NumberFormat.NumberDecimalSeparator == "," && valueResult.AttemptedValue.LastIndexOf(".") > 0)
                {
                    culture = new CultureInfo("en"); 
                }
                else if (Thread.CurrentThread.CurrentCulture.NumberFormat.NumberDecimalSeparator == "." && valueResult.AttemptedValue.LastIndexOf(",") > 0)
                {
                    culture = new CultureInfo("it");
                }

                actualValue = Convert.ToDecimal(valueResult.AttemptedValue, culture);

            }
            catch (FormatException e)
            {
                modelState.Errors.Add(e);
            }
        }

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

        return actualValue;
    }
}
于 2021-01-20T10:27:36.470 に答える
-4

スクリプトの次のリンクにコメントするだけです。

<%--<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>--%>
于 2014-02-21T07:54:20.640 に答える