私の問題は、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?.
}
10進数の値を送信する場合は、データを文字列化する必要があります。
data: JSON.stringify({ Price: 5.0 })
これは、デフォルトのバインダでは小数が整数と見なされるためです。
もちろん、DecimalModelBinder
の使用に変更することもできます。これについては、次のリンクで詳しく説明しています。
これは文化の問題である可能性があります
アクションに送信する文字列が現在のカルチャーに準拠していることを確認してください。 (10進数のセパレーター.
,
を確認してください)
例
例えばフランスのサーバーでは、99.1
は99,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)
}).
まず、jqueryオブジェクトでそのメソッドを使用しようとしているため、toFixed
をこの方法で使用するとエラーが発生します。
使用するparseFloat(value).toFixed(2)
データをJSONとして渡すことをお勧めします。
data: JSON.stringify({ price: price }),
contentType: "application/json; charset=utf-8"
コンテンツタイプを含めるように注意してください。バインダーがリクエストのデータを解析する方法を知るために必要になる場合があります。
変更してみてください
var price = Number($('#price').val().toFixed(2));
に
var price = parseFloat($('#price').val()).toFixed(2);
私にとってはこの方法のみが機能します:
type: "POST",
data: 'price': parseFloat($(#price).val()).toFixed(2).replace(".", ","),
success: function(data){
...
}
それはおそらく環境における現在の文化に依存しています。私はそれが誰かを助けることを願っています。
エラーは、投稿時の価格データ:{price:価格}が実際のデータ:{price:null}であることを示しています。
したがって、このコード、
Number($( '#price')。val()。toFixed(2));
null値を返しています。より正確には、Number()呼び出しをparseFloat()に変更して、正しい結果を取得します。以下はテスト済みで動作するコードです。
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());
}
より複雑なモデルをバインドする必要があったため、文字列化ソリューションは私が望んでいたものではありませんでした。だから私は小数を受け入れるようにデフォルトのモデルバインダーを拡張する方法を示すこの記事を見つけました。
これが 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 ...
}
変更してみてください:
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」