Этот вопрос не является дубликатом вопроса. Коллекцию сервисов нельзя изменить, поскольку она доступна только для чтения. В своем коде я ничего не делаю с builder.Services. после var app = builder.Build();
Проблема
Я я обновляю проект веб-API ASP.NET Core на C# с .NET 6 на .NET 8. Все, что я сделал, это изменил
Код: Выделить всё
net6.0
enable
enable
Debug;Release;StoutBI;UAT
Код: Выделить всё
net8.0
В этом проекте код компилируется, но каждый раз, когда я вызываю конечную точку, я получаю следующее исключение:
System.InvalidOperationException: коллекцию служб нельзя изменить, поскольку она доступна только для чтения.
в Microsoft.Extensions.DependencyInjection.ServiceCollection.ThrowReadOnlyException()
в Microsoft.Extensions.DependencyInjection.ServiceCollection.System.Collections.Generic.ICollection.Add(элемент ServiceDescriptor)
в Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddTransient(IServiceCollection Services, Type serviceType, TypeimplementationType)
в Microsoft.Extensions.DependencyInjection.OptionsBuilderExtensions.ValidateOnStart[TOptions](OptionsBuilder)
Код: Выделить всё
1 optionsBuilder) at Microsoft.Extensions.DependencyInjection.MetricsServiceExtensions.AddMetrics(IServiceCollection services) at Microsoft.Extensions.DependencyInjection.HttpClientFactoryServiceCollectionExtensions.AddHttpClient(IServiceCollection services) at Microsoft.Identity.Web.MicrosoftIdentityWebAppAuthenticationBuilderWithConfiguration.b__1_0(ConfidentialClientApplicationOptions options) at Microsoft.Extensions.Options.OptionsFactory
в System.Lazy
Код: Выделить всё
1.ViaFactory(LazyThreadSafetyMode mode) at System.Lazy
в System.Lazy
Код: Выделить всё
1.CreateValue() at Microsoft.Extensions.Options.OptionsCache
Код: Выделить всё
3 createOptions, TArg factoryArgument) at Microsoft.Extensions.Options.OptionsMonitor
в Microsoft.Identity.Web.MicrosoftIdentityWebAppAuthenticationBuilder.c__DisplayClass11_0.b__0(параметры OpenIdConnectOptions, ImergedOptionsStore mergedOptionsMonitor, IOptionsMonitor
Код: Выделить всё
1 ccaOptionsMonitor, IOptions
в Microsoft.Extensions.Options.ConfigureNamedOptions
Код: Выделить всё
4.Configure(String name, TOptions options) at Microsoft.Extensions.Options.OptionsFactory
в System.Lazy
Код: Выделить всё
1.ViaFactory(LazyThreadSafetyMode mode) --- End of stack trace from previous location --- at System.Lazy
в Microsoft.Extensions.Options.OptionsCache
Код: Выделить всё
1.GetOrAdd[TArg](String name, Func
в Microsoft.Extensions.Options.OptionsMonitor
Код: Выделить всё
1.Get(String name) at Microsoft.AspNetCore.Authentication.AuthenticationHandler
в Microsoft.AspNetCore.Authentication.AuthenticationHandlerProvider.GetHandlerAsync(контекст HttpContext, строковая аутентификацияScheme)
в Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke( HttpContext context)
в Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext)
в Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)
Точная трассировка стека немного варьируется в зависимости от вызванной конечной точки, но исключением является каждый раз одно и то же (часть выше --- Конец трассировки стека из предыдущего местоположения ---).
Изменилось ли что-то в .NET 8 в как приложение должно быть создано и настроено? Или что-то изменилось в библиотеках, и они настраиваются по-другому?
Вот основная часть кода в моем Program.cs (без изменений по сравнению с .NET 6):
Код: Выделить всё
DbContextOptionsBuilder optionsBuilder = new DbContextOptionsBuilder();
optionsBuilder.UseSqlServer(InternalApiUtil.DbConnectionString);
// Add manually constructed DbContext
builder.Services.AddScoped(sp => new ReadWriteContext(optionsBuilder.Options));
builder.Services.AddScoped();
builder.Services.AddScoped();
builder.Services.AddControllers(options =>
{
options.Filters.Add();
}).AddJsonOptions(options =>
{
options.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
options.JsonSerializerOptions.DictionaryKeyPolicy = JsonNamingPolicy.CamelCase;
});
builder.Services.AddCors(options =>
{
options.AddPolicy(CORS_POLICY_NAME, builder =>
{
builder.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod();
});
});
builder.Services.AddEndpointsApiExplorer(); // I've tried with this line commented-out: no difference
builder.Services.AddSwaggerGen();
builder.Services.AddScoped(typeof(IGenericRepository), typeof(GenericRepository));
builder.Services.AddScoped(typeof(MyCacheService));
builder.Services.AddMemoryCache(opt =>
{
opt.SizeLimit = 1024;
});
builder.Services.AddAutoMapper(ProfileFactory.CustomProfiles);
string[] initialScopes = { "Group.Read.All", "User.Read.All" };
IConfigurationSection azureAd = builder.Configuration.GetSection("AzureAd");
builder.Services.AddAuthentication()
.AddJwtBearer()
.AddMicrosoftIdentityWebApp(azureAd)
.EnableTokenAcquisitionToCallDownstreamApi(initialScopes)
.AddMicrosoftGraph()
.AddInMemoryTokenCaches();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseDefaultFiles();
app.UseStaticFiles();
app.UseCors(CORS_POLICY_NAME);
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
#if DEBUG
app.Run(InternalApiUtil.LOCAL_SERVER_URL);
#else
app.Run();
#endif
if (baseRule != null && InternalApiUtil.LogDebugStatements)
{
baseRule.EnableLoggingForLevel(NLog.LogLevel.Debug);
}
logger.Info("Ready to run.");
Что пробовали
Вместо того чтобы делать что-то вручную, я попробовал использовать .NET Upgrade Assistant, но он вносит точно такие же изменения.
Я также обновил все пакеты, как предложил NuGet, но с тем же результатом.
Подробнее здесь: https://stackoverflow.com/questions/792 ... he-service