Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# asp.net passing an object with a long property to front end changes it's value [duplicate]

I'm building an application with a react.js front-end (although I'm fairly sure that's not relevant to the issue) and an asp.net back-end (targeting net5.0, not sure if that's relevant). When I call to the back-end API, I get back an object that includes, in part, an ID it generated based on the data passed in, that is of type long in C# (a 64 bit int). The behavior that I'm seeing is that the variable in C# and the variable read from the response on the front end are different. They appear to drift after about 16-17 digits.

Is this expected? Is there any way to get around it?

Code to reproduce / Pictures of what I see:

C#

[HttpPost]
[Route("test")]
public object TestPassingLongInObject()
{
    /* actual logic omitted for brevity */

    var rv = new
    {
        DataReadIn = new { /* omitted */ },
        ValidationResult = new ValidationResult(),
        GeneratedID =  long.Parse($"922337203{new Random().Next(int.MaxValue):0000000000}") // close to long.MaxValue
    };

    Console.WriteLine($"ID in C# controller method: {rv.GeneratedID}");

    return rv;
}

Console output: ID in C# controller method: 9223372030653055062

Chrome Dev Tools:

Response seen by Chrome dev tools

When I try to access the ID on the front-end I get the incorrect ID ending in 000 instead of 062.

Edit 1: It's been suggested that this is because JavaScript's Number.MAX_SAFE_INTEGER is less than the value I'm passing. I don't believe that is the reason, but perhaps I'm wrong and someone can enlighten me. On the JS side, I'm using BigInt, precisely because the number I'm passing is too large for Number. The issue is before I'm parsing the result to a JS object though (unless Chrome is doing that automatically, leading to the picture referenced in the issue).

Edit 2: Based on the answers below, it looks like perhaps JS is parsing the value to a number before I'm parsing it to a BigInt, so I'm still losing precision. Can someone more familiar with the web confirm this?

like image 927
Brian Avatar asked Mar 01 '23 17:03

Brian


1 Answers

JavaScript is interpreting that value as a number which is a 64-bit floating-point number. If you want to keep that value, you're better off passing it back as a string.

Example JS to demonstrate the problem:

var value = 9223372030653055062;
console.log(value);
console.log(typeof(value));
like image 99
DavidG Avatar answered Mar 05 '23 17:03

DavidG