gpt4 book ai didi

asp.net-mvc - 反序列化 JSON 时 MVC3 RTM 失败数字类型强制

转载 作者:行者123 更新时间:2023-12-01 02:50:56 25 4
gpt4 key购买 nike

简单地将数据序列化为“application/json; charset=utf-8”格式在 MVC3(可能还有旧版本)中行为不端。发生的情况是一个可以为空的数字都以 null 结尾,而“十进制”类型的数字在 javascript 对象(到 JSON)中序列化它们并将它们保留为数字而不是字符串时以 0 结尾。

这是说明这种不当行为的示例代码
- - - 这个例子是使用 jquery-1.4.4.js 和 jquery.json-2.2.js 创建的 - - - -

HomeController.cs:

public class HomeController : Controller
{
public ActionResult Index()
{
ViewBag.SaveUrl = Url.Action("Save", "Home", new { inspectionFormID = Guid.Empty }, Request.Url.Scheme);
return View();
}

public JsonResult Save(Guid inspectionFormID, JsonTest result)
{
return Json(result);
}

public class JsonTest
{
public double Double { get; set; }
public double? DoubleNull { get; set; }

public decimal Decimal { get; set; }
public decimal? DecimalNull { get; set; }

public Double Double2 { get; set; }
public Double? Double2Null { get; set; }

public Decimal Decimal2 { get; set; }
public Decimal? Decimal2Null { get; set; }

public Single Single { get; set; }
public Single? SingleNull { get; set; }

public float Float { get; set; }
public float? FloatNull { get; set; }

public int Int { get; set; }
public int? IntNull { get; set; }

public Int64 Int64 { get; set; }
public Int64? Int64Null { get; set; }
}

}

索引.cshtml:
    @{
ViewBag.Title = "Index";
}

<h2>Index</h2>

<b>@ViewBag.SaveUrl</b>
<br />
<hr />
<br />

<h3>Integral Numbers</h3>
<button type="button" class="a">Clicky</button>
<div></div>

<h3>Decimal Numbers (xx.0)</h3>
<button type="button" class="b">Clicky</button>
<div></div>

<h3>Decimal Numbers (xx.5)</h3>
<button type="button" class="c">Clicky</button>
<div></div>

<h3>Integral Numbers as strings</h3>
<button type="button" class="d">Clicky</button>
<div></div>

<h3>Decimal Numbers as strings (xx.5)</h3>
<button type="button" class="e">Clicky</button>
<div></div>

<script type="text/javascript">

$(function () {
var saveUrl = '@ViewBag.SaveUrl';

var printObj = function (inObj, destx) {
var dest = $('<table>').appendTo(destx),
dst1 = $('<tr>').appendTo(dest),
dst2 = $('<tr>').appendTo(dest);
for (var p in inObj) {
$('<th>', { text: p, css: { color: 'red', padding: '3px', background: '#dedede' } }).appendTo(dst1);
$('<td>', { text: inObj[p] || 'null' }).appendTo(dst2);
}
};

$('button.a').click(function () {
var curr = $(this).next(),
outR = {
Double: 12,
DoubleNull: 13,
Decimal: 14,
DecimalNull: 15,
Double2: 16,
Double2Null: 17,
Decimal2: 18,
Decimal2Null: 19,
Single: 20,
SingleNull: 21,
Float: 22,
FloatNull: 23,
Int: 24,
IntNull: 25,
Int64: 26,
Int64Null: 27
};

$('<hr />').appendTo(curr);
printObj(outR, curr);

$.ajax({
type: 'POST',
url: saveUrl,
contentType: "application/json; charset=utf-8",
dataType: 'json',

data: $.toJSON({
inspectionFormID: 'fbde6eda-dde6-4ba9-b82d-3a35349415f0',

result: outR
}),

error: function (jqXHR, textStatus, errorThrown) {
alert('save failed');
},

success: function (data, textStatus, jqXHR) {
printObj(data, curr);
}
});
});

$('button.b').click(function () {
var curr = $(this).next(),
outR = {
Double: 12.0,
DoubleNull: 13.0,
Decimal: 14.0,
DecimalNull: 15.0,
Double2: 16.0,
Double2Null: 17.0,
Decimal2: 18.0,
Decimal2Null: 19.0,
Single: 20.0,
SingleNull: 21.0,
Float: 22.0,
FloatNull: 23.0,
Int: 24.0,
IntNull: 25.0,
Int64: 26.0,
Int64Null: 27.0
};

$('<hr />').appendTo(curr);
printObj(outR, curr);

$.ajax({
type: 'POST',
url: saveUrl,
contentType: "application/json; charset=utf-8",
dataType: 'json',

data: $.toJSON({
inspectionFormID: 'fbde6eda-dde6-4ba9-b82d-3a35349415f0',

result: outR
}),

error: function (jqXHR, textStatus, errorThrown) {
alert('save failed');
},

success: function (data, textStatus, jqXHR) {
printObj(data, curr);
}
});
});

$('button.c').click(function () {
var curr = $(this).next(),
outR = {
Double: 12.5,
DoubleNull: 13.5,
Decimal: 14.5,
DecimalNull: 15.5,
Double2: 16.5,
Double2Null: 17.5,
Decimal2: 18.5,
Decimal2Null: 19.5,
Single: 20.5,
SingleNull: 21.5,
Float: 22.5,
FloatNull: 23.5,
Int: 24.5,
IntNull: 25.5,
Int64: 26.5,
Int64Null: 27.5
};

$('<hr />').appendTo(curr);
printObj(outR, curr);

$.ajax({
type: 'POST',
url: saveUrl,
contentType: "application/json; charset=utf-8",
dataType: 'json',

data: $.toJSON({
'inspectionFormID': 'fbde6eda-dde6-4ba9-b82d-3a35349415f0',

'result': outR
}),

error: function (jqXHR, textStatus, errorThrown) {
alert('save failed');
},

success: function (data, textStatus, jqXHR) {
printObj(data, curr);
}
});
});

$('button.d').click(function () {
var curr = $(this).next(),
outR = {
Double: '12',
DoubleNull: '13',
Decimal: '14',
DecimalNull: '15',
Double2: '16',
Double2Null: '17',
Decimal2: '18',
Decimal2Null: '19',
Single: '20',
SingleNull: '21',
Float: '22',
FloatNull: '23',
Int: '24',
IntNull: '25',
Int64: '26',
Int64Null: '27'
};

$('<hr />').appendTo(curr);
printObj(outR, curr);

$.ajax({
type: 'POST',
url: saveUrl,
contentType: "application/json; charset=utf-8",
dataType: 'json',
data: $.toJSON({
'inspectionFormID': 'fbde6eda-dde6-4ba9-b82d-3a35349415f0',

'result': outR
}),

error: function (jqXHR, textStatus, errorThrown) {
alert('save failed');
},

success: function (data, textStatus, jqXHR) {
printObj(data, curr);
}
});
});

$('button.e').click(function () {
var curr = $(this).next(),
outR = {
Double: '12.5',
DoubleNull: '13.5',
Decimal: '14.5',
DecimalNull: '15.5',
Double2: '16.5',
Double2Null: '17.5',
Decimal2: '18.5',
Decimal2Null: '19.5',
Single: '20.5',
SingleNull: '21.5',
Float: '22.5',
FloatNull: '23.5',
Int: '24.5',
IntNull: '25.5',
Int64: '26.5',
Int64Null: '27.5'
};

$('<hr />').appendTo(curr);
printObj(outR, curr);

$.ajax({
type: 'POST',
url: saveUrl,
contentType: "application/json; charset=utf-8",
dataType: 'json',
data: $.toJSON({
'inspectionFormID': 'fbde6eda-dde6-4ba9-b82d-3a35349415f0',

'result': outR
}),

error: function (jqXHR, textStatus, errorThrown) {
alert('save failed');
},

success: function (data, textStatus, jqXHR) {
printObj(data, curr);
}
});
});
});

</script>

运行它单击每个按钮一次,然后查看之前/之后。提前感谢您为解决此问题提供的任何见解、更正或帮助。

您还可以下载上面列出的代码示例,并在此链接查看官方错误报告: http://aspnet.codeplex.com/workitem/8114

编辑:我包含这张图片是为了帮助大家了解这里发生的事情

click here to see the screenshot of the included example running

基本上: { propertyThatIsADecimal: 54 } 在服务器上变为 { propertyThatIsADecimal: 0 } 用于不同场景中的多种不同数字类型,似乎没有任何押韵或理由。

最佳答案

原因是当 MVC 遇到一个数字时,它会将其视为 Int32。 .因此,出于某种原因,没有来自 Int32 的转换器。说一个DecimalNullable<Int64> .有几种方法可以解决这个问题。字符串,就像您在项目中已有的那样,或者用于创建自定义模型绑定(bind)器。

public class JsonTestModelBinder : IModelBinder {
public virtual object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) {
JsonTest result = new JsonTest();

foreach (var property in typeof(JsonTest).GetProperties()) {
//the value provider starts with the name of the property we're binding to
//i'm not sure if this changed or not as i don't recall having to do this
//before - you can remove "result." if your needs don't require it
var value = bindingContext.ValueProvider.GetValue("result." + property.Name);
if (value != null && value.RawValue != null) {
//are we binding to a nullable?
if (property.PropertyType.IsGenericType && property.PropertyType.GetGenericTypeDefinition().Equals(typeof(Nullable<>))) {
property.SetValue(result, Convert.ChangeType(value.AttemptedValue, new NullableConverter(property.PropertyType).UnderlyingType), null);
} else {
property.SetValue(result, Convert.ChangeType(value.AttemptedValue, property.PropertyType), null);
}
}
}

return result;
}
}

我不完全确定为什么我们仍然无法从 Int32 转换至 Decimal但问题存在于 MVC 的 ValueProviderResult.ConvertSimpleType .它正在使用 TypeDescriptor.GetConverter(your propertyType)并且这些类型没有可用的转换。

我不喜欢这种特殊的方法,但它是你目前唯一可用的方法。

关于asp.net-mvc - 反序列化 JSON 时 MVC3 RTM 失败数字类型强制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5045623/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com