ASP.NET Core基于文件的应用程序,默认序列化导致错误

后端开发 2026-07-10

我想把一个有基础API的简单应用,改造成一个用来对数字进行计算以产生负载的应用,作为一个概念验证的基于文件的应用。

generate-load-server.cs:

#! /usr/bin/env dotnet run
#:sdk Microsoft.NET.Sdk.Web

using Microsoft.AspNetCore.Mvc;
using System.Numerics;

var builder = WebApplication.CreateBuilder();
builder.Services.AddRequestTimeouts();
var app = builder.Build();
app.UseRequestTimeouts();
app.MapGet("/api/generate-load", ([FromQuery] int? n = default) =>
{
    var iterations = n ?? 100000000;
    ArgumentOutOfRangeException.ThrowIfNegative(iterations);
    if (Vector.IsHardwareAccelerated)
        return CalculatePi.MonteCarloVector(iterations);
    return CalculatePi.MonteCarloBasic(iterations);
}).WithRequestTimeout(TimeSpan.FromMinutes(10));

await app.RunAsync("http://localhost:8123");

static class CalculatePi
{
    // implementations...
    public static decimal MonteCarloBasic(int iter, int? seed = default)
    {
        // ...
    }

    public static decimal MonteCarloVector(int iter, int? seed = default)
    {
        // ...
    }
}

应用程序启动得很正常,但当我调用API时,遇到了一个怪异的JSON序列化错误,和我的代码完全无关。

$ dotnet run generate-load-server.cs
info: Microsoft.Hosting.Lifetime[14]
      Now listening on: http://localhost:8123
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
      Hosting environment: Production
info: Microsoft.Hosting.Lifetime[0]
      Content root path: S:\test
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
      Request starting HTTP/1.1 GET http://localhost:8123/api/generate-load?n=1000000000 - - -
bunch of requests...
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
      Request starting HTTP/1.1 GET http://localhost:8123/api/generate-load?n=1000000000 - - -
fail: Microsoft.AspNetCore.Server.Kestrel[13]
      Connection id "0HNKN8P5M7SO1", Request id "0HNKN8P5M7SO1:00000001": An unhandled exception was thrown by the application.
      System.NotSupportedException: JsonTypeInfo metadata for type 'System.Decimal' was not provided by TypeInfoResolver of type '[]'. If using source generation, ensure that all root types passed to the serializer have been annotated with 'JsonSerializableAttribute', along with any types that might be serialized polymorphically.
         at System.Text.Json.ThrowHelper.ThrowNotSupportedException_NoMetadataForType(Type type, IJsonTypeInfoResolver resolver)
         at System.Text.Json.JsonSerializerOptions.GetTypeInfoInternal(Type type, Boolean ensureConfigured, Nullable`1 ensureNotNull, Boolean resolveIfMutable, Boolean fallBackToNearestAncestorType)
         at System.Text.Json.JsonSerializerOptions.GetTypeInfo(Type type)
         at Microsoft.AspNetCore.Http.Generated.<GeneratedRouteBuilderExtensions_g>F6DE0C89F6F8484B82B89F44B1C0701B89E2552B502F347FA7B76C4935F008AA9__GeneratedRouteBuilderExtensionsCore.<>c.<MapGet0>b__2_1(Delegate del, RequestDelegateFactoryOptions options, RequestDelegateMetadataResult inferredMetadataResult) in C:\Users\jeff.mercado\AppData\Local\Temp\dotnet\runfile\generate-load-server-165da69c96b0c4ee5a200ebe536be4b7bab40e25dcdf29f15f61d54c4d7f526c\obj\debug\Microsoft.AspNetCore.Http.RequestDelegateGenerator\Microsoft.AspNetCore.Http.RequestDelegateGenerator.RequestDelegateGenerator\GeneratedRouteBuilderExtensions.g.cs:line 92
         at Microsoft.AspNetCore.Routing.RouteEndpointDataSource.CreateRouteEndpointBuilder(RouteEntry entry, RoutePattern groupPrefix, IReadOnlyList`1 groupConventions, IReadOnlyList`1 groupFinallyConventions)
         at Microsoft.AspNetCore.Routing.RouteEndpointDataSource.get_Endpoints()
         at Microsoft.AspNetCore.Routing.CompositeEndpointDataSource.CreateEndpointsUnsynchronized()
         at Microsoft.AspNetCore.Routing.CompositeEndpointDataSource.EnsureEndpointsInitialized()
         at Microsoft.AspNetCore.Routing.CompositeEndpointDataSource.get_Endpoints()
         at Microsoft.AspNetCore.Routing.DataSourceDependentCache`1.Initialize()
         at System.Threading.LazyInitializer.EnsureInitializedCore[T](T& target, Boolean& initialized, Object& syncLock, Func`1 valueFactory)
         at Microsoft.AspNetCore.Routing.Matching.DataSourceDependentMatcher..ctor(EndpointDataSource dataSource, Lifetime lifetime, Func`1 matcherBuilderFactory)
         at Microsoft.AspNetCore.Routing.Matching.DfaMatcherFactory.CreateMatcher(EndpointDataSource dataSource)
         at Microsoft.AspNetCore.Routing.EndpointRoutingMiddleware.InitializeCoreAsync()
      --- End of stack trace from previous location ---
         at Microsoft.AspNetCore.Routing.EndpointRoutingMiddleware.<Invoke>g__AwaitMatcher|10_0(EndpointRoutingMiddleware middleware, HttpContext httpContext, Task`1 matcherTask)
         at Microsoft.AspNetCore.Routing.EndpointRoutingMiddleware.<Invoke>g__AwaitMatcher|10_0(EndpointRoutingMiddleware middleware, HttpContext httpContext, Task`1 matcherTask)
         at Microsoft.AspNetCore.Routing.EndpointRoutingMiddleware.<Invoke>g__AwaitMatcher|10_0(EndpointRoutingMiddleware middleware, HttpContext httpContext, Task`1 matcherTask)
         at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 application)
         at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 application)
         at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 application)
bunch of this error...

System.NotSupportedException: JsonTypeInfo metadata for type 'System.Decimal' was not provided by TypeInfoResolver of type '[]'. If using source generation, ensure that all root types passed to the serializer have been annotated with 'JsonSerializableAttribute', along with any types that might be serialized polymorphically.

那它突然就不知道如何对decimal类型进行序列化吗?

同样的代码在LINQPad运行时没有问题,但出于某种原因,序列化配置存在问题。我需要添加额外的引用/配置吗?为什么要为内置的decimal重新定义序列化?

我已经安装了.NET 11的预览版本,并添加一个 global.json 文件来强制它使用.NET 10,但这没有任何效果。

global.json:

{
  "sdk": {
    "version": "10.0.201"
  }
}

这个错误的原因是什么?我该如何修复?

解决方案

基于文件的应用默认使用原生的提前编译(AOT):

File-based apps enable native ahead-of-time (AOT) compilation by default. This feature produces optimized, self-contained executables with faster startup and a smaller memory footprint.

你可以启用ASP.NET Core的源生代码生成支持(你已经发现过):

[JsonSerializable(typeof(decimal))]
internal partial class MyJsonContext : JsonSerializerContext { }
builder.Services.ConfigureHttpJsonOptions(o =>
{
    o.SerializerOptions.TypeInfoResolverChain.Insert(0, MyJsonContext.Default);
});

或者通过相应的设置禁用本地AOT,例如在文件顶部指定以下内容:

:property PublishAot=false

对于像ASP.NET Core服务这样的长期运行应用,我建议直接禁用AOT选项。

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章