You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET 6升级至8启动报错:AugmentedRealityController实例创建失败

.NET 6升级至.NET 8后启动异常问题分析与解决

问题描述

将Web应用目标框架从.NET 6升级到.NET 8,且所有Microsoft包更新至8.0.4版本后,启动时抛出以下异常:

Application startup exception
System.InvalidOperationException: The configuration is invalid. Creating the instance for type AugmentedRealityController failed. Property set method not found.
 ---> SimpleInjector.ActivationException: Property set method not found.
 ---> System.ArgumentException: Property set method not found.
   at System.Reflection.RuntimePropertyInfo.SetValue(Object obj, Object value, BindingFlags invokeAttr, Binder binder, Object[] index, CultureInfo culture)
   at System.Reflection.RuntimePropertyInfo.SetValue(Object obj, Object value, Object[] index)
   at evoTrace.Web.Api.Security.ValidationParametersBuilder.<get_ValidationParametersOptionsMapperAction>b__8_0(TokenValidationParameters parameters) in C:\Projekte\evoTraceGS\src\Core\Web\evoTrace.Web.Api\Security\ValidationParametersBuilder.cs:line 52
   at Microsoft.Extensions.Options.ConfigureNamedOptions`1.Configure(String name, TOptions options)
   at Microsoft.Extensions.Options.OptionsFactory`1.Create(String name)
   at Microsoft.Extensions.Options.UnnamedOptionsManager`1.get_Value()
   at evoTrace.Core.Security.JwtValidator..ctor(IOptions`1 validationParameters) in C:\Projekte\evoTraceGS\src\Core\Core\evoTrace.Core.Security\JwtValidator.cs:line 21
   at lambda_method47(Closure)
   at SimpleInjector.Scope.CreateAndCacheInstanceInternal(ScopedRegistration registration, Dictionary`2 cache)
   at SimpleInjector.Scope.GetInstanceInternal(ScopedRegistration registration)
   at lambda_method48(Closure)
   at SimpleInjector.Scope.CreateAndCacheInstanceInternal(ScopedRegistration registration, Dictionary`2 cache)
   at SimpleInjector.Scope.GetInstanceInternal(ScopedRegistration registration)
   at lambda_method50(Closure)
   at SimpleInjector.Scope.CreateAndCacheInstanceInternal(ScopedRegistration registration, Dictionary`2 cache)
   at SimpleInjector.Scope.GetInstanceInternal(ScopedRegistration registration)
   at SimpleInjector.Scope.GetInstance[TImplementation](ScopedRegistration registration, Scope scope)
   at lambda_method52(Closure)
   at SimpleInjector.Scope.CreateAndCacheInstanceInternal(ScopedRegistration registration, Dictionary`2 cache)
   at SimpleInjector.Scope.GetInstanceInternal(ScopedRegistration registration)
   at lambda_method58(Closure)
   at SimpleInjector.Scope.CreateAndCacheInstanceInternal(ScopedRegistration registration, Dictionary`2 cache)
   at SimpleInjector.Scope.GetInstanceInternal(ScopedRegistration registration)
   at lambda_method244(Closure)
   at SimpleInjector.InstanceProducer.BuildAndReplaceInstanceCreatorAndCreateFirstInstance()
   at SimpleInjector.InstanceProducer.GetInstance()
   --- End of inner exception stack trace ---
   at SimpleInjector.InstanceProducer.GetInstance()
   at SimpleInjector.InstanceProducer.VerifyInstanceCreation()
   --- End of inner exception stack trace ---
   at SimpleInjector.InstanceProducer.VerifyInstanceCreation()
   at SimpleInjector.Container.VerifyInstanceCreation(InstanceProducer[] producersToVerify, Scope verificationScope)
   at SimpleInjector.Container.VerifyThatAllRootObjectsCanBeCreated(Scope verificationScope)
   at SimpleInjector.Container.VerifyInternal(Boolean suppressLifestyleMismatchVerification)
   at SimpleInjector.Container.Verify(VerificationOption option)
   at SimpleInjector.Container.Verify()
   at evoTrace.Web.Api.Startup.Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory) in C:\Projekte\evoTraceGS\src\Core\Web\evoTrace.Web.Api\Startup.cs:line 212
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
   at System.Reflection.MethodBaseInvoker.InvokeDirectByRefWithFewArgs(Object obj, Span`1 copyOfArgs, BindingFlags invokeAttr)
   at System.Reflection.MethodBaseInvoker.InvokeWithFewArgs(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at Microsoft.AspNetCore.Hosting.ConfigureBuilder.Invoke(Object instance, IApplicationBuilder builder)
   at SimpleInjector.Integration.AspNetCore.RequestScopingStartupFilter.<>c__DisplayClass3_0.<Configure>b__0(IApplicationBuilder builder)
   at SimpleInjector.Integration.AspNetCore.RequestScopingStartupFilter.<>c__DisplayClass3_0.<Configure>b__0(IApplicationBuilder builder)
   at Microsoft.AspNetCore.Hosting.GenericWebHostService.StartAsync(CancellationToken cancellationToken)

困惑点:应用完全不涉及AugmentedRealityController,但报错却指向该控制器。

报错触发代码位于ValidationParametersBuilder类:

internal class ValidationParametersBuilder
{
    internal ValidationParametersBuilder()
    {     
        var secretKey = ConfigReader.ReadStringValue(EnvVars.JWT_SECRET_KEY);

        var issuer = ConfigReader.ReadStringValue(EnvVars.JWT_ISSUER);

        var audience = ConfigReader.ReadStringValue(EnvVars.JWT_AUDIENCE);

        var signingKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(secretKey));
        SigningCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256);
        ValidationParameters = new TokenValidationParameters
        {
            ValidIssuer = issuer,
            ValidateIssuer = true,
            ValidAudience = audience,
            ValidateAudience = true,
            ValidateIssuerSigningKey = true,
            IssuerSigningKey = signingKey,
            RequireExpirationTime = false,
            ValidateLifetime = true,           
            ClockSkew = TimeSpan.Zero
        };
    }

    public SigningCredentials SigningCredentials { get; }

    public TokenValidationParameters ValidationParameters { get; }

    public Action<TokenValidationParameters> ValidationParametersOptionsMapperAction =>
        (parameters) =>
        {
            foreach (var propertyInfo in ValidationParameters.GetType().GetProperties())
            {
                var value = propertyInfo.GetValue(ValidationParameters);
                if (value != null)
                {
                    propertyInfo.SetValue(parameters, value); // <---- 异常触发点
                }
            }
        };
}

Startup.cs相关配置代码:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory)
{
    AdjustEnvironment(env);

    app.UseSimpleInjector(_container);
    app.UseMiddleware<ErrorHandlingMiddleware>(_container);
    app.UseHealthChecks("/health", new HealthCheckOptions
    {
        ResultStatusCodes =
        {
            [HealthStatus.Healthy] = StatusCodes.Status200OK,
            [HealthStatus.Degraded] = StatusCodes.Status200OK,
            [HealthStatus.Unhealthy] = StatusCodes.Status503ServiceUnavailable
        },
        AllowCachingResponses = false
    });
    app.UseRouting();

    if (env.IsDevelopment())
    {
        app.UseCors(ConfigureSecurity.CORS_ALLOW_ANY_ORIGINS);
    }
    else
    {
        app.UseCors(ConfigureSecurity.CORS_ALLOW_SPECIFIC_ORIGINS);
    }

    app.UseAuthentication();
    app.UseAuthorization();

    app.UseMiddleware<NotificationMiddleware>(_container);

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
    });

    
    _container.Verify();
}

问题原因

  1. TokenValidationParameters属性变更:.NET 8的Microsoft.IdentityModel.Tokens.TokenValidationParameters类新增了部分只读属性(无set方法),而你的代码通过反射遍历所有属性并尝试设置值,遇到这些只读属性时就会抛出"Property set method not found"异常。

  2. AugmentedRealityController的误导性:SimpleInjector容器验证时会尝试创建所有根对象(包括所有控制器),AugmentedRealityController的依赖链最终会用到JwtValidator,而JwtValidator依赖IOptions<TokenValidationParameters>,配置该Options时触发了反射赋值的异常。报错指向该控制器只是因为它是触发依赖链验证的入口之一,并非控制器本身存在问题。

解决方案

方案一:过滤可写属性

修改ValidationParametersOptionsMapperAction,仅对有set方法的属性进行赋值:

public Action<TokenValidationParameters> ValidationParametersOptionsMapperAction =>
    (parameters) =>
    {
        foreach (var propertyInfo in ValidationParameters.GetType().GetProperties())
        {
            // 只处理拥有set方法的属性
            if (propertyInfo.CanWrite)
            {
                var value = propertyInfo.GetValue(ValidationParameters);
                if (value != null)
                {
                    propertyInfo.SetValue(parameters, value);
                }
            }
        }
    };

方案二:手动指定属性赋值

放弃反射批量赋值,手动指定需要配置的属性,避免版本变更带来的未知风险:

public Action<TokenValidationParameters> ValidationParametersOptionsMapperAction =>
    (parameters) =>
    {
        parameters.ValidIssuer = ValidationParameters.ValidIssuer;
        parameters.ValidateIssuer = ValidationParameters.ValidateIssuer;
        parameters.ValidAudience = ValidationParameters.ValidAudience;
        parameters.ValidateAudience = ValidationParameters.ValidateAudience;
        parameters.ValidateIssuerSigningKey = ValidationParameters.ValidateIssuerSigningKey;
        parameters.IssuerSigningKey = ValidationParameters.IssuerSigningKey;
        parameters.RequireExpirationTime = ValidationParameters.RequireExpirationTime;
        parameters.ValidateLifetime = ValidationParameters.ValidateLifetime;
        parameters.ClockSkew = ValidationParameters.ClockSkew;
        // 根据业务需求添加其他需要配置的属性
    };

内容的提问来源于stack exchange,提问作者Maxim

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 02:45:56