C#asp.net将具有长属性的对象传递给前端会改变它的值[重复]
Posted
技术标签:
【中文标题】C#asp.net将具有长属性的对象传递给前端会改变它的值[重复]【英文标题】:C# asp.net passing an object with a long property to front end changes it's value [duplicate] 【发布时间】:2021-05-27 00:56:03 【问题描述】:我正在构建一个带有 react.js 前端(尽管我相当确定这与问题无关)和 asp.net 后端(针对 net5.0,不确定是否相关)的应用程序)。当我调用后端 API 时,我得到一个对象,其中部分包括它根据传入的数据生成的 ID,它是 C# 中的 long 类型(64 位 int)。我看到的行为是 C# 中的变量和从前端响应中读取的变量是不同的。它们似乎在大约 16-17 位数字后漂移。
这是预期的吗?有什么办法可以解决吗?
复制代码/我看到的图片:
C#
[HttpPost]
[Route("test")]
public object TestPassingLongInObject()
/* actual logic omitted for brevity */
var rv = new
DataReadIn = new /* omitted */ ,
ValidationResult = new ValidationResult(),
GeneratedID = long.Parse($"922337203new Random().Next(int.MaxValue):0000000000") // close to long.MaxValue
;
Console.WriteLine($"ID in C# controller method: rv.GeneratedID");
return rv;
控制台输出:ID in C# controller method: 9223372030653055062
Chrome 开发工具:
当我尝试访问前端的 ID 时,我得到了以 000 而不是 062 结尾的错误 ID。
编辑 1:有人建议这是因为 javascript 的 Number.MAX_SAFE_INTEGER
小于我传递的值。我不相信这是原因,但也许我错了,有人可以启发我。在 JS 方面,我使用BigInt
,正是因为我传递的数字对于Number
来说太大了。问题是在我将结果解析为 JS 对象之前(除非 Chrome 自动执行此操作,导致问题中引用的图片)。
编辑 2:根据下面的答案,看起来 JS 可能在我将值解析为 BigInt 之前将其解析为数字,所以我仍然在丢失精度。更熟悉网络的人可以证实这一点吗?
【问题讨论】:
我认为这是Javascript或Json格式的限制,您可以使用字符串而不是long吗?long.Parse()
大约是最慢的方法。使用9223372030000000000 + rand.Next(int.MaxValue)
另外,重新使用 Random 实例(使其成为静态成员)。这不仅是一个弱性能优化,还可以确保您不会意外使用相同的种子。
@JoelCoehoorn 省略了实际逻辑。这实际上并不是生成 ID 的方式,只是说明问题的一种方式。真正的公式中没有使用 Random()。
@phuzi 我编辑了我的问题,说我在前端使用 BigInt,但也许 JS 仍在使用 Number?我对网络开发还不是很熟悉。
如果在您有机会使用 BigInt 之前将响应解析为 JS 对象,则该数字将已经转换为常规 JS 数字,精度将降低。您可以调试 AJAX 请求/响应来确认这一点。
【参考方案1】:
JavaScript 引擎(显然)无法创建这么大的数字。尝试打开您的控制台并输入以下内容:
var myLong = 9223372030653055062;
console.log(myLong);
您也可以检查9223372030653055 > Number.MAX_SAFE_INTEGER
,作为您越界的指针。
【讨论】:
【参考方案2】:JavaScript 将该值解释为 number
,它是一个 64 位浮点数。如果您想保留该值,最好将其作为字符串传回。
示例 JS 演示问题:
var value = 9223372030653055062;
console.log(value);
console.log(typeof(value));
【讨论】:
有没有办法告诉 JS 使用 BigInt(我认为应该解决 Number 的问题)? 我很确定没有办法阻止浏览器这样做。【参考方案3】:Javascript 中数字的最大大小为 2^53 - 1,即 9007199254740991。在 C# 中,long 为 2^64 - 1,更大。所以“9223372030653055062”作为 C# long 但不能作为 JavaScript 数字,因为它太大了。如果这个 ID 正在使用 long 的数据库中使用,我建议您将它作为字符串传递给 JavaScript。
【讨论】:
OP 的数字是 9223372030653055000 比您在 9007199254740991 处为Number
声明的最大值大得多,使得 Number
的最大大小远大于 2^53-1【参考方案4】:
虽然原因是数字大于 JS 可以准确表示的数字,但您似乎已经被 Chrome 的 Dev Tools Preview 分心了。这只是一个“有用”的预览,不一定是事实。
开发工具预览显示了一个有用的响应视图。我假设 AJAX 响应是使用 application/json 的内容类型传输的,因此 Chrome 有助于将 JSON 解析为 JS 对象并让您预览响应。检查响应选项卡,这是您的 AJAX 代码实际接收的内容。
有可能在您有机会对该数字使用BigInt
之前解析JSON,从而限制精度。您还没有向我们展示您的 AJAX 代码,所以这是我的最佳猜测。
唯一的解决方案是将其序列化为字符串,然后添加手动步骤将字符串转换为BigInt
。
jsObject.generatedId = BigInt(jsObject.generatedId);
如果您将其用作 ID,那么您不妨将其作为字符串保存在客户端,因为您不太可能使用它来进行任何计算。
【讨论】:
以上是关于C#asp.net将具有长属性的对象传递给前端会改变它的值[重复]的主要内容,如果未能解决你的问题,请参考以下文章
如何从 jQuery ajax 调用将复杂对象传递给 ASP.NET WebApi GET?
如何将参数传递给 jQuery document.ready() 函数(ASP.NET MVC、C#)
我应该如何将多个参数传递给 ASP.Net Web API GET?
在 ASP.Net Core 项目中使用 ADO.Net 将 JSON 类型作为参数传递给 SQL Server 2016 存储过程