对“asp.net core WebApi”的 ajax 调用返回一个奇怪/奇怪的值

Posted

技术标签:

【中文标题】对“asp.net core WebApi”的 ajax 调用返回一个奇怪/奇怪的值【英文标题】:ajax call to "asp.net core WebApi" returns a strange/weird value 【发布时间】:2021-11-13 09:53:20 【问题描述】:

我有一个 api 控制器,它返回一个包含两个对象列表的对象。

我希望当我使用 ajax 调用这个 api 时我会得到这个结果: 一个包含长值的对象和两个对象列表:


"userId":26000000000000228,
"paidInvoices":
["id":13060000000000039,"total":10,
"id":13060000000000040,"total":20,
"id":13060000000000041,"total":30],
"unPaidInvoices":
["id":15060000000000039,"total":10,
"id":15060000000000040,"total":20,
"id":15060000000000041,"total":30]

但我得到了意想不到的重复 ids(都以 40 结尾):


"userId":26000000000000228,
"paidInvoices":
["id":13060000000000040,"total":10,
"id":13060000000000040,"total":20,
"id":13060000000000040,"total":30],
"unPaidInvoices":
["id":15060000000000040,"total":10,
"id":15060000000000040,"total":20,
"id":15060000000000040,"total":30]

代码:

public class Invoice

    public long Id  get; set; 
    public decimal Total  get; set; 


public class Invoices

    public long UserId  get; set; 
    public List<Invoice> PaidInvoices  get; set; 
    public List<Invoice> UnPaidInvoices  get; set; 


[Route("NetApi/[controller]")]
[ApiController]
public class PurchasePaymentController : ControllerBase

    [HttpGet("Search/id")]
    public Task<Invoices> Search(long id)
    
        var paid = new List<Invoice>
        
            new Invoice Id = 13060000000000039, Total = 10,
            new Invoice Id = 13060000000000040, Total = 20,
            new Invoice Id = 13060000000000041, Total = 30
        ;
        var unPaid = new List<Invoice>
        
            new Invoice Id = 15060000000000039, Total = 10,
            new Invoice Id = 15060000000000040, Total = 20,
            new Invoice Id = 15060000000000041, Total = 30
        ;
        return Task.FromResult(new Invoices UserId = id, PaidInvoices = paid, UnPaidInvoices = unPaid);
    

我已经尝试返回 JsonResult,它没有任何区别。 我从这个不使用任何布局的 razorPage 调用它:

@page
@model MyWebSite.Pages.Test.IndexModel
@
    Layout = null;

<html>
<head>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
</head>
<body>
<h1>Welcome</h1>
<div id="result"></div>
<script>

    // if I use $.ajax or $.get , the result is the same (weird/unexpected result) 
    $(function () 
        $.ajax(
            type: "GET",
            url: "@Url.RouteUrl("NetApi", new controller = "PurchasePayment", action = "Search", id = 26000000000000228)",
            contentType: "application/json; charset=utf-8",
            dataType: "json",
            success: getCallback
        );
    );

    $(function() 
        debugger;
        $.get("@Url.RouteUrl("NetApi", new controller = "PurchasePayment", action = "Search", id = 26000000000000228)",
            getCallback, "json");
    );

    function getCallback(response) 
        console.log(JSON.stringify(response));
        debugger;
    


    // but this load method works fine

    $(function() 
        $("#result").load("@Url.RouteUrl("NetApi", new controller = "PurchasePayment", action = "Search", id = 26000000000000228)");
    );


</script>
</body>
</html>

在我的 Startup.cs 中

// ConfigureServices
services.AddMvc().AddNewtonsoftJson(options =>
                options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore
            );

// Configure
app.UseStaticFiles();
        app.UseRouting();
        app.UseAuthentication();
        app.UseAuthorization();
        app.UseEndpoints(endpoints =>
        
            endpoints.MapControllerRoute(
                    name: "default",
                    pattern: "controller=Home/action=Index/id?");
            endpoints.MapControllerRoute(
             name: "api",
             pattern: "api/controller/action/id?",
             defaults: new  controller = "login", action = "Index" );

            endpoints.MapControllerRoute(
                name: "NetApi",
                pattern: "NetApi/controller/action/id?");
            endpoints.MapRazorPages();
        );

【问题讨论】:

是的,我已经尝试过了。 @格雷格 【参考方案1】:

我使用 Postman 测试了您的 Api,一切正常。所以问题是javascript。如果您在 Id long 数字中删除了一个零,那么在 javascript 中也一切正常。

15060000000000039 这个值实际上并没有超过 JavaScript 中的最大数值,但是,这个值超出了“整数精度”的范围,有时也被称为整数精度大小,即 2 pow 53。发送了错误的数字:相反,文字 15060000000000039 和 13060000000000041 只能精确表示为 13060000000000040,因此 JavaScript 中从来没有正确的数值。 (积分范围约为 +/- 253。)问题在于 javascript 对大整数进行四舍五入的方式。

因此,如果您仍要使用 javascript,我可以提供的解决方法是将这些长数字作为字符串发送。或者,如果您需要处理数字,则有很多 javascript BigInt 库。但似乎您不需要它,因为它们只是发票号码。所以把你的班级改成这个

public class Invoice

    public string Id  get; set; 
    public decimal Total  get; set; 

和数据

var paid = new List<Invoice>
        
            new Invoice Id = "13060000000000039", Total = 10,
            new Invoice Id = "13060000000000040", Total = 20,
     .... and so on

或者也许使用这个,你不需要改变任何东西

public class Invoice

        [JsonIgnore]
        public long Id  get; set; 
        public string InvoiceId  get  return Id.ToString();  
        public decimal Total  get; set; 


【讨论】:

以上是关于对“asp.net core WebApi”的 ajax 调用返回一个奇怪/奇怪的值的主要内容,如果未能解决你的问题,请参考以下文章

对“asp.net core WebApi”的 ajax 调用返回一个奇怪/奇怪的值

[Asp.Net Core]ASP.NET Core WebApi使用Swagger生成api说明文档看这篇就够了

在 ASP.NET Core WebAPI 中实现 JSON 合并补丁

Asp.net Core WebAPI 基于资源的控制器级别之外的授权

带有 ASP.NET Core WebAPI 的 Dart 中的令牌刷新并发问题

Asp.Net Core WebAPI+PostgreSQL部署在Docker中