web-dev-qa-db-ja.com

C#MVCコントローラーはAjaxから10進数または2倍の値を取得できませんPOST request

私の問題は、ajaxを介してdoubleまたはdecimalをC#MVCコントローラーに送信しようとすると、値が常にnullになることです。値を文字列として送信でき、整数を問題なく送信できます。小数を含む値を送信できないのはなぜですか?クライアントから送信されたリクエストを確認すると、正しい値があります(フォームデータはprice=84.50)。

エラー:

パラメータディクショナリに、null不可のタイプ「System.Decimal」のパラメータ「price」のnullエントリが含まれています

HTML:

 <input type="number" step="1" class="form-control" name="price" id="price">
 <button type="button" class="btn btn-success">Send</button>

JavaScript:

$('.btn-success').click(function () {

    //var price = $('#price').val(); - Did not work
    //var price = Number($('#price').val()); Did not work
    var price = Number($('#price').val()).toFixed(2); // Does not work

    $.ajax({
        url: 'PriceFunction',
        type: 'POST',
        data: {
            price: price,
        }
    }).done(function () {

    }).fail(function () {
        console.log("Error in ajaxfunction!");
    });
});

C#:

    [HttpPost]
    public void PriceFunction(decimal price)
    {
     // I have tried with decimal, double and double?.     
    }
15
Ogglas

10進数の値を送信する場合は、データを文字列化する必要があります。

data: JSON.stringify({ Price: 5.0 })

これは、デフォルトのバインダでは小数が整数と見なされるためです。

もちろん、DecimalModelBinderの使用に変更することもできます。これについては、次のリンクで詳しく説明しています。

ASP.NET MVC3 JSON 10進数バインディングの問題

10
Stuart

これは文化の問題である可能性があります

アクションに送信する文字列が現在のカルチャーに準拠していることを確認してください。 (10進数のセパレーター.,を確認してください)

例えばフランスのサーバーでは、99.199,1として認識されませんが、0に変換されます。

ソリューション

その場合、1つの解決策は、Web.Configにカルチャーを定義することです。

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

Or、クライアント側でセパレータを適切なものに置き換えます。

Ajax呼び出しのdataパラメーターに渡されたJSONを文字列化してみてください。これでうまくいくはずです。

var data = { price: price };

$.ajax({
    url: 'PriceFunction',
    type: 'POST',
    data: JSON.stringify(data)
}).
2

まず、jqueryオブジェクトでそのメソッドを使用しようとしているため、toFixedをこの方法で使用するとエラーが発生します。

使用する
parseFloat(value).toFixed(2)

1
Esko

データをJSONとして渡すことをお勧めします。

data: JSON.stringify({ price: price }),
contentType: "application/json; charset=utf-8"

コンテンツタイプを含めるように注意してください。バインダーがリクエストのデータを解析する方法を知るために必要になる場合があります。

1

変更してみてください

var price = Number($('#price').val().toFixed(2));

var price = parseFloat($('#price').val()).toFixed(2);
0

私にとってはこの方法のみが機能します:

type: "POST",
data: 'price': parseFloat($(#price).val()).toFixed(2).replace(".", ","),
success: function(data){
...
}

それはおそらく環境における現在の文化に依存しています。私はそれが誰かを助けることを願っています。

0
gutkol

エラーは、投稿時の価格データ:{price:価格}が実際のデータ:{price:null}であることを示しています。

したがって、このコード、

Number($( '#price')。val()。toFixed(2));

null値を返しています。より正確には、Number()呼び出しをparseFloat()に変更して、正しい結果を取得します。以下はテスト済みで動作するコードです。

enter image description here

Ajaxコール:

    <script language="javascript">
    function TriggerAction()
    {
        alert($('#price').val());
        var price = parseFloat($('#price').val()).toFixed(2);
        alert(price);
        callAjax("PriceFunction", price);
    }

    function ajaxCallResult(result, action)
    {
        if (action==="PriceFunction")
        {
            alert(result);
        }
        else if (action==="error")
        {
            alert("Error: "+action+" call failed!");
        }
    }

    function callAjax(action, param) {

        $.ajax({
            type: "POST",
            url: "/Home/"+action,    
            data: {param: param},
            success: function (result) {
                ajaxCallResult(result, action);
            },
            error: function (req, status, error) {
                ajaxCallResult("error", action);
            }
        });
    }
</script>

<input type="number" step="1" class="form-control" name="price" id="price">
<button type="button" class="btn btn-success" onclick="TriggerAction();">Send</button>

MVCコード:

        [HttpPost]
        public ActionResult PriceFunction(decimal param)
        {
            return Json("OK Got the value:" + param.ToString());
        }
0

より複雑なモデルをバインドする必要があったため、文字列化ソリューションは私が望んでいたものではありませんでした。だから私は小数を受け入れるようにデフォルトのモデルバインダーを拡張する方法を示すこの記事を見つけました。

これが haacked.com のコードです。

最初にIModelBinderを拡張します。

using System;
using System.Globalization;
using System.Web.Mvc;

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;
        try {
            actualValue = Convert.ToDecimal(valueResult.AttemptedValue, 
                CultureInfo.CurrentCulture);
        }
        catch (FormatException e) {
            modelState.Errors.Add(e);
        }

        bindingContext.ModelState.Add(bindingContext.ModelName, modelState);
        return actualValue;
    }
}

次に、このバインダーを登録します。

protected void Application_Start() {
    AreaRegistration.RegisterAllAreas();

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

    // All other stuff ...
}
0
gtu

変更してみてください:

    public class test
    {
        public decimal Price { get; set; }
    }

    [HttpPost]
    public void Test(test whatever)
    {
        // I have tried with decimal, double and double?.     
    }

プロパティのNameとdataTypeに注意:Ajax呼び出しの「json」

0
RomainV