diff --git a/.github/workflows/api-e2e-mssql-multitenant.yml b/.github/workflows/api-e2e-mssql-multitenant.yml index a5c8109d5..47b00e2b4 100644 --- a/.github/workflows/api-e2e-mssql-multitenant.yml +++ b/.github/workflows/api-e2e-mssql-multitenant.yml @@ -46,6 +46,9 @@ jobs: - name: Copy admin api common folder to docker context run: cp -r ../EdFi.Ods.AdminApi.Common ../../Docker/Application + - name: Copy Instance Management Provisioner folder to docker context + run: cp -r ../EdFi.AdminConsole.InstanceMgrWorker.Provisioner ../../Docker/Application + - name: Copy nuget config to docker context run: cp ../NuGet.Config ../../Docker/Application diff --git a/.github/workflows/api-e2e-mssql-singletenant.yml b/.github/workflows/api-e2e-mssql-singletenant.yml index 3964ceed0..431a69c93 100644 --- a/.github/workflows/api-e2e-mssql-singletenant.yml +++ b/.github/workflows/api-e2e-mssql-singletenant.yml @@ -46,6 +46,9 @@ jobs: - name: Copy admin api common folder to docker context run: cp -r ../EdFi.Ods.AdminApi.Common ../../Docker/Application + - name: Copy Instance Management Provisioner folder to docker context + run: cp -r ../EdFi.AdminConsole.InstanceMgrWorker.Provisioner ../../Docker/Application + - name: Copy nuget config to docker context run: cp ../NuGet.Config ../../Docker/Application diff --git a/.github/workflows/api-e2e-pgsql-multitenant.yml b/.github/workflows/api-e2e-pgsql-multitenant.yml index fadc070a5..cbd920608 100644 --- a/.github/workflows/api-e2e-pgsql-multitenant.yml +++ b/.github/workflows/api-e2e-pgsql-multitenant.yml @@ -46,6 +46,9 @@ jobs: - name: Copy admin api common folder to docker context run: cp -r ../EdFi.Ods.AdminApi.Common ../../Docker/Application + - name: Copy Instance Management Provisioner folder to docker context + run: cp -r ../EdFi.AdminConsole.InstanceMgrWorker.Provisioner ../../Docker/Application + - name: Copy nuget config to docker context run: cp ../NuGet.Config ../../Docker/Application diff --git a/.github/workflows/api-e2e-pgsql-singletenant.yml b/.github/workflows/api-e2e-pgsql-singletenant.yml index 18c2b0588..80a3f0808 100644 --- a/.github/workflows/api-e2e-pgsql-singletenant.yml +++ b/.github/workflows/api-e2e-pgsql-singletenant.yml @@ -41,6 +41,7 @@ jobs: cp -r ../EdFi.Ods.AdminApi ../../Docker/Application cp -r ../EdFi.Ods.AdminApi.AdminConsole ../../Docker/Application cp -r ../EdFi.Ods.AdminApi.Common ../../Docker/Application + cp -r ../EdFi.AdminConsole.InstanceMgrWorker.Provisioner ../../Docker/Application - name: Copy nuget config to docker context run: cp ../NuGet.Config ../../Docker/Application diff --git a/Application/Directory.Packages.props b/Application/Directory.Packages.props index 513a86f14..2a70ef89d 100644 --- a/Application/Directory.Packages.props +++ b/Application/Directory.Packages.props @@ -59,7 +59,7 @@ - + @@ -78,6 +78,26 @@ - + + + + + + + + + + + + + + + + + + + + + diff --git a/Application/Ed-Fi-ODS-AdminApi.sln b/Application/Ed-Fi-ODS-AdminApi.sln index 975da9156..bca7cc508 100644 --- a/Application/Ed-Fi-ODS-AdminApi.sln +++ b/Application/Ed-Fi-ODS-AdminApi.sln @@ -30,6 +30,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EdFi.Ods.AdminApi.Common.Un EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EdFi.Ods.AdminApi.AdminConsole.UnitTests", "EdFi.Ods.AdminApi.AdminConsole.UnitTests\EdFi.Ods.AdminApi.AdminConsole.UnitTests.csproj", "{7C919128-B651-4756-8625-A8F7882FA9A4}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EdFi.AdminConsole.InstanceMgrWorker.Configuration", "EdFi.AdminConsole.InstanceMgrWorker.Provisioner\EdFi.AdminConsole.InstanceMgrWorker.Configuration.csproj", "{1370EB3F-F4B7-4396-8BBD-B8572908A6B3}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -102,6 +104,14 @@ Global {7C919128-B651-4756-8625-A8F7882FA9A4}.Release|Any CPU.Build.0 = Release|Any CPU {7C919128-B651-4756-8625-A8F7882FA9A4}.Release|x64.ActiveCfg = Release|Any CPU {7C919128-B651-4756-8625-A8F7882FA9A4}.Release|x64.Build.0 = Release|Any CPU + {1370EB3F-F4B7-4396-8BBD-B8572908A6B3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1370EB3F-F4B7-4396-8BBD-B8572908A6B3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1370EB3F-F4B7-4396-8BBD-B8572908A6B3}.Debug|x64.ActiveCfg = Debug|Any CPU + {1370EB3F-F4B7-4396-8BBD-B8572908A6B3}.Debug|x64.Build.0 = Debug|Any CPU + {1370EB3F-F4B7-4396-8BBD-B8572908A6B3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1370EB3F-F4B7-4396-8BBD-B8572908A6B3}.Release|Any CPU.Build.0 = Release|Any CPU + {1370EB3F-F4B7-4396-8BBD-B8572908A6B3}.Release|x64.ActiveCfg = Release|Any CPU + {1370EB3F-F4B7-4396-8BBD-B8572908A6B3}.Release|x64.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Application/Ed-Fi-ODS-AdminApi.sln.DotSettings b/Application/Ed-Fi-ODS-AdminApi.sln.DotSettings index 2bdd201f0..aa0b9430a 100644 --- a/Application/Ed-Fi-ODS-AdminApi.sln.DotSettings +++ b/Application/Ed-Fi-ODS-AdminApi.sln.DotSettings @@ -130,6 +130,10 @@ See the LICENSE and NOTICES files in the project root for more information.<Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> <Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" /> <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy><Descriptor Staticness="Static" AccessRightKinds="Private" Description="Static readonly fields (private)"><ElementKinds><Kind Name="READONLY_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" /></Policy> + <Policy><Descriptor Staticness="Instance" AccessRightKinds="Protected, ProtectedInternal, Internal, Public, PrivateProtected" Description="Instance fields (not private)"><ElementKinds><Kind Name="FIELD" /><Kind Name="READONLY_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></Policy> + <Policy><Descriptor Staticness="Static" AccessRightKinds="Protected, ProtectedInternal, Internal, Public, PrivateProtected" Description="Static fields (not private)"><ElementKinds><Kind Name="FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></Policy> + <Policy><Descriptor Staticness="Any" AccessRightKinds="Any" Description="Local constants"><ElementKinds><Kind Name="LOCAL_CONSTANT" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></Policy> <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> @@ -188,6 +192,7 @@ See the LICENSE and NOTICES files in the project root for more information.True True True + True True True True diff --git a/Application/EdFi.AdminConsole.InstanceMgrWorker.Provisioner/EdFi.AdminConsole.InstanceMgrWorker.Configuration.csproj b/Application/EdFi.AdminConsole.InstanceMgrWorker.Provisioner/EdFi.AdminConsole.InstanceMgrWorker.Configuration.csproj new file mode 100644 index 000000000..08b5dc996 --- /dev/null +++ b/Application/EdFi.AdminConsole.InstanceMgrWorker.Provisioner/EdFi.AdminConsole.InstanceMgrWorker.Configuration.csproj @@ -0,0 +1,31 @@ + + + + net8.0 + enable + enable + c0ecdf69-7e69-4ccf-9854-b82da0d9e253 + Debug;Release + true + + + + + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + diff --git a/Application/EdFi.AdminConsole.InstanceMgrWorker.Provisioner/Provisioners/ConfigConnectionStringsProvider.cs b/Application/EdFi.AdminConsole.InstanceMgrWorker.Provisioner/Provisioners/ConfigConnectionStringsProvider.cs new file mode 100644 index 000000000..323560e7b --- /dev/null +++ b/Application/EdFi.AdminConsole.InstanceMgrWorker.Provisioner/Provisioners/ConfigConnectionStringsProvider.cs @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: Apache-2.0 +// Licensed to the Ed-Fi Alliance under one or more agreements. +// The Ed-Fi Alliance licenses this file to you under the Apache License, Version 2.0. +// See the LICENSE and NOTICES files in the project root for more information. + +using Microsoft.Extensions.Configuration; + +namespace EdFi.AdminConsole.InstanceMgrWorker.Configuration.Provisioners +{ + public class ConfigConnectionStringsProvider(IConfiguration config) : IMgrWorkerConfigConnectionStringsProvider + { + private string _tenant = string.Empty; + private readonly IConfiguration _config = config; + + public int Count => ConnectionStringProviderByName.Keys.Count; + + public IDictionary ConnectionStringProviderByName + { + get + { +#pragma warning disable CS8619 // Nullability of reference types in value doesn't match target type. + if (!string.IsNullOrEmpty(_tenant) && !_tenant.Equals("default", StringComparison.OrdinalIgnoreCase)) + return _config.GetSection($"Tenants:{_tenant}:ConnectionStrings") + .GetChildren() + .ToDictionary(k => k.Key, v => v.Value); + else + return _config.GetSection("ConnectionStrings") + .GetChildren() + .ToDictionary(k => k.Key, v => v.Value); +#pragma warning restore CS8619 // Nullability of reference types in value doesn't match target type. + } + } + + public void SetTenant(string tenant) => _tenant = tenant; + + public string GetConnectionString(string name) => ConnectionStringProviderByName[name]; + } +} diff --git a/Application/EdFi.AdminConsole.InstanceMgrWorker.Provisioner/Provisioners/DbInstanceType.cs b/Application/EdFi.AdminConsole.InstanceMgrWorker.Provisioner/Provisioners/DbInstanceType.cs new file mode 100644 index 000000000..0a72c919c --- /dev/null +++ b/Application/EdFi.AdminConsole.InstanceMgrWorker.Provisioner/Provisioners/DbInstanceType.cs @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: Apache-2.0 +// Licensed to the Ed-Fi Alliance under one or more agreements. +// The Ed-Fi Alliance licenses this file to you under the Apache License, Version 2.0. +// See the LICENSE and NOTICES files in the project root for more information. + +namespace EdFi.AdminConsole.InstanceMgrWorker.Configuration.Provisioners +{ + public enum DbInstanceType + { + Minimal, + Sample + } +} diff --git a/Application/EdFi.AdminConsole.InstanceMgrWorker.Provisioner/Provisioners/IInstanceProvisioner.cs b/Application/EdFi.AdminConsole.InstanceMgrWorker.Provisioner/Provisioners/IInstanceProvisioner.cs new file mode 100644 index 000000000..1621065bc --- /dev/null +++ b/Application/EdFi.AdminConsole.InstanceMgrWorker.Provisioner/Provisioners/IInstanceProvisioner.cs @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: Apache-2.0 +// Licensed to the Ed-Fi Alliance under one or more agreements. +// The Ed-Fi Alliance licenses this file to you under the Apache License, Version 2.0. +// See the LICENSE and NOTICES files in the project root for more information. + +namespace EdFi.AdminConsole.InstanceMgrWorker.Configuration.Provisioners +{ + public interface IInstanceProvisioner + { + void AddDbInstance(string instanceName, DbInstanceType instanceType); + + void AddDbInstance(string instanceName, DbInstanceType instanceType, bool useSuffix); + + void DeleteDbInstances(params string[] deletedClientKeys); + + void RenameDbInstances(string oldName, string newName); + + InstanceStatus GetDbInstanceStatus(string clientKey); + + void ResetDemoDbInstance(); + + string[] GetInstancesDatabases(); + + string GetOdsConnectionString(string instanceName); + + string Tenant { get; set; } + + Task AddDbInstanceAsync(string instanceName, DbInstanceType instanceType); + + Task AddDbInstanceAsync(string instanceName, DbInstanceType instanceType, bool useSuffix); + + Task DeleteDbInstancesAsync(params string[] deletedClientKeys); + + Task RenameDbInstancesAsync(string oldName, string newName); + + Task GetDbInstanceStatusAsync(string clientKey); + + Task ResetDemoDbInstanceAsync(); + + Task GetInstancesDatabasesAsync(); + + Task CopyDbInstanceAsync(string originalDatabaseName, string newDatabaseName); + + Task CheckDatabaseExists(string instanceName); + } +} diff --git a/Application/EdFi.AdminConsole.InstanceMgrWorker.Provisioner/Provisioners/IMgrWorkerConfigConnectionStringsProvider.cs b/Application/EdFi.AdminConsole.InstanceMgrWorker.Provisioner/Provisioners/IMgrWorkerConfigConnectionStringsProvider.cs new file mode 100644 index 000000000..f2624f1e9 --- /dev/null +++ b/Application/EdFi.AdminConsole.InstanceMgrWorker.Provisioner/Provisioners/IMgrWorkerConfigConnectionStringsProvider.cs @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: Apache-2.0 +// Licensed to the Ed-Fi Alliance under one or more agreements. +// The Ed-Fi Alliance licenses this file to you under the Apache License, Version 2.0. +// See the LICENSE and NOTICES files in the project root for more information. + +using EdFi.Ods.Common.Configuration; + +namespace EdFi.AdminConsole.InstanceMgrWorker.Configuration.Provisioners; + +public interface IMgrWorkerConfigConnectionStringsProvider : IConfigConnectionStringsProvider +{ + void SetTenant(string tenant); +} diff --git a/Application/EdFi.AdminConsole.InstanceMgrWorker.Provisioner/Provisioners/IMgrWorkerIDatabaseNameBuilder.cs b/Application/EdFi.AdminConsole.InstanceMgrWorker.Provisioner/Provisioners/IMgrWorkerIDatabaseNameBuilder.cs new file mode 100644 index 000000000..7017154ba --- /dev/null +++ b/Application/EdFi.AdminConsole.InstanceMgrWorker.Provisioner/Provisioners/IMgrWorkerIDatabaseNameBuilder.cs @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: Apache-2.0 +// Licensed to the Ed-Fi Alliance under one or more agreements. +// The Ed-Fi Alliance licenses this file to you under the Apache License, Version 2.0. +// See the LICENSE and NOTICES files in the project root for more information. + +using EdFi.Admin.DataAccess.Utils; + +namespace EdFi.AdminConsole.InstanceMgrWorker.Configuration.Provisioners; + +public interface IMgrWorkerIDatabaseNameBuilder : IDatabaseNameBuilder +{ + string OdsDatabaseName(string? tenant, string databaseName); +} diff --git a/Application/EdFi.AdminConsole.InstanceMgrWorker.Provisioner/Provisioners/InstanceDatabaseNameBuilder.cs b/Application/EdFi.AdminConsole.InstanceMgrWorker.Provisioner/Provisioners/InstanceDatabaseNameBuilder.cs new file mode 100644 index 000000000..feaef2c0b --- /dev/null +++ b/Application/EdFi.AdminConsole.InstanceMgrWorker.Provisioner/Provisioners/InstanceDatabaseNameBuilder.cs @@ -0,0 +1,71 @@ +// SPDX-License-Identifier: Apache-2.0 +// Licensed to the Ed-Fi Alliance under one or more agreements. +// The Ed-Fi Alliance licenses this file to you under the Apache License, Version 2.0. +// See the LICENSE and NOTICES files in the project root for more information. + +using EdFi.Ods.Common.Database; +using EdFi.Ods.Common.Extensions; + +namespace EdFi.AdminConsole.InstanceMgrWorker.Configuration.Provisioners +{ + public class InstanceDatabaseNameBuilder : IMgrWorkerIDatabaseNameBuilder + { + private const string TemplatePrefix = "Ods_"; + private const string TemplateMinimalDatabase = TemplatePrefix + "Minimal_Template"; + + private string? _tenant { get; set; } + private readonly Lazy _databaseNameTemplate; + + public InstanceDatabaseNameBuilder(IMgrWorkerConfigConnectionStringsProvider connectionStringsProvider, + IDbConnectionStringBuilderAdapterFactory connectionStringBuilderFactory) + { + _databaseNameTemplate = new Lazy( + () => + { + if (!string.IsNullOrEmpty(_tenant)) + connectionStringsProvider.SetTenant(_tenant); + + if (!connectionStringsProvider.ConnectionStringProviderByName.ContainsKey("EdFi_Ods")) + { + return string.Empty; + } + + var connectionStringBuilder = connectionStringBuilderFactory.Get(); + + connectionStringBuilder.ConnectionString = connectionStringsProvider.GetConnectionString("EdFi_Ods"); + + return connectionStringBuilder.DatabaseName; + }); + } + + public string DemoSandboxDatabase + { + get => "EdFi_Ods"; + } + + public string EmptyDatabase => throw new NotImplementedException(); + + public string MinimalDatabase + { + get => DatabaseName(_tenant, TemplateMinimalDatabase); + } + + public string SampleDatabase => throw new NotImplementedException(); + + public string SandboxNameForKey(string key) => throw new NotImplementedException(); + + public string KeyFromSandboxName(string sandboxName) => throw new NotImplementedException(); + + public string TemplateSandboxNameForKey(string sandboxKey) => throw new NotImplementedException(); + + public string OdsDatabaseName(string? tenant, string databaseName) => DatabaseName(tenant, TemplatePrefix + databaseName); + + private string DatabaseName(string? tenant, string databaseName) + { + _tenant = tenant; + return _databaseNameTemplate.Value.IsFormatString() + ? string.Format(_databaseNameTemplate.Value, databaseName) + : _databaseNameTemplate.Value; + } + } +} diff --git a/Application/EdFi.AdminConsole.InstanceMgrWorker.Provisioner/Provisioners/InstanceProvisionerBase.cs b/Application/EdFi.AdminConsole.InstanceMgrWorker.Provisioner/Provisioners/InstanceProvisionerBase.cs new file mode 100644 index 000000000..36b4d6bc3 --- /dev/null +++ b/Application/EdFi.AdminConsole.InstanceMgrWorker.Provisioner/Provisioners/InstanceProvisionerBase.cs @@ -0,0 +1,123 @@ +// SPDX-License-Identifier: Apache-2.0 +// Licensed to the Ed-Fi Alliance under one or more agreements. +// The Ed-Fi Alliance licenses this file to you under the Apache License, Version 2.0. +// See the LICENSE and NOTICES files in the project root for more information. + +using System.Data.Common; +using EdFi.Ods.Common.Extensions; +using Microsoft.Extensions.Configuration; + +namespace EdFi.AdminConsole.InstanceMgrWorker.Configuration.Provisioners +{ + public abstract class InstanceProvisionerBase : IInstanceProvisioner + { + protected string _tenant; + protected readonly IConfiguration _configuration; + protected readonly IMgrWorkerConfigConnectionStringsProvider _connectionStringsProvider; + protected readonly IMgrWorkerIDatabaseNameBuilder _databaseNameBuilder; + + protected InstanceProvisionerBase(IConfiguration configuration, + IMgrWorkerConfigConnectionStringsProvider connectionStringsProvider, IMgrWorkerIDatabaseNameBuilder databaseNameBuilder) + { + _tenant = string.Empty; + _configuration = configuration; + _connectionStringsProvider = connectionStringsProvider; + _databaseNameBuilder = databaseNameBuilder; + + CommandTimeout = int.TryParse(_configuration.GetSection("SandboxAdminSQLCommandTimeout").Value, out int timeout) + ? timeout + : 30; + } + + protected int CommandTimeout { get; } + + protected string? ConnectionString { get; set; } + + public string Tenant + { + get => _tenant; + set + { + _tenant = value; + _connectionStringsProvider.SetTenant(value); + ConnectionString = _connectionStringsProvider.GetConnectionString("EdFi_Master"); + } + } + + public string GetOdsConnectionString(string instanceName) + { + if (string.IsNullOrEmpty(instanceName)) + throw new ArgumentNullException(nameof(instanceName)); + + return string.Format(_connectionStringsProvider.GetConnectionString("EdFi_Ods"), _databaseNameBuilder.OdsDatabaseName(null, instanceName)); + } + + public string[] GetInstancesDatabases() => GetInstancesDatabasesAsync().GetResultSafely(); + + public void AddDbInstance(string instanceName, DbInstanceType instanceType) + => AddDbInstanceAsync(instanceName, instanceType).WaitSafely(); + + public void AddDbInstance(string instanceName, DbInstanceType instanceType, bool useSuffix) + => AddDbInstanceAsync(instanceName, instanceType, useSuffix).WaitSafely(); + + public void DeleteDbInstances(params string[] deletedClientKeys) => DeleteDbInstancesAsync(deletedClientKeys).WaitSafely(); + + public void RenameDbInstances(string oldName, string newName) => RenameDbInstancesAsync(oldName, newName).WaitSafely(); + + public InstanceStatus GetDbInstanceStatus(string clientKey) => GetDbInstanceStatusAsync(clientKey).GetResultSafely(); + + public void ResetDemoDbInstance() => ResetDemoDbInstanceAsync().WaitSafely(); + + public async Task AddDbInstanceAsync(string instanceName, DbInstanceType instanceType) + { + await AddDbInstanceAsync(instanceName, instanceType, false); + } + public async Task AddDbInstanceAsync(string instanceName, DbInstanceType instanceType, bool useSuffix) + { + var newInstanceName = _databaseNameBuilder.OdsDatabaseName(_tenant, instanceName); + await DeleteDbInstancesAsync(newInstanceName).ConfigureAwait(false); + + switch (instanceType) + { + case DbInstanceType.Minimal: + await CopyDbInstanceAsync( + _databaseNameBuilder.MinimalDatabase, + newInstanceName) + .ConfigureAwait(false); + + break; + case DbInstanceType.Sample: + await CopyDbInstanceAsync( + _databaseNameBuilder.SampleDatabase, + newInstanceName) + .ConfigureAwait(false); + + break; + default: + throw new ArgumentOutOfRangeException(nameof(instanceType), instanceType, "Unhandled DbInstanceType provided"); + } + } + + public abstract Task DeleteDbInstancesAsync(params string[] deletedClientKeys); + + public abstract Task GetDbInstanceStatusAsync(string clientKey); + + public async Task ResetDemoDbInstanceAsync() + { + var tmpName = Guid.NewGuid().ToString("N"); + await CopyDbInstanceAsync(_databaseNameBuilder.SampleDatabase, tmpName).ConfigureAwait(false); + await DeleteDbInstancesAsync(_databaseNameBuilder.DemoSandboxDatabase).ConfigureAwait(false); + await RenameDbInstancesAsync(tmpName, _databaseNameBuilder.DemoSandboxDatabase).ConfigureAwait(false); + } + + public abstract Task GetInstancesDatabasesAsync(); + + public abstract Task RenameDbInstancesAsync(string oldName, string newName); + + public abstract Task CopyDbInstanceAsync(string originalDatabaseName, string newDatabaseName); + + protected abstract DbConnection CreateConnection(); + + public abstract Task CheckDatabaseExists(string instanceName); + } +} diff --git a/Application/EdFi.AdminConsole.InstanceMgrWorker.Provisioner/Provisioners/InstanceStatus.cs b/Application/EdFi.AdminConsole.InstanceMgrWorker.Provisioner/Provisioners/InstanceStatus.cs new file mode 100644 index 000000000..35877bec8 --- /dev/null +++ b/Application/EdFi.AdminConsole.InstanceMgrWorker.Provisioner/Provisioners/InstanceStatus.cs @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: Apache-2.0 +// Licensed to the Ed-Fi Alliance under one or more agreements. +// The Ed-Fi Alliance licenses this file to you under the Apache License, Version 2.0. +// See the LICENSE and NOTICES files in the project root for more information. +namespace EdFi.AdminConsole.InstanceMgrWorker.Configuration.Provisioners +{ + public class InstanceStatus + { + public string? Name { get; set; } + + public byte Code { get; set; } + + public string? Description { get; set; } + + public static InstanceStatus ErrorStatus() + { + return new InstanceStatus + { + Code = byte.MaxValue, + Description = "ERROR" + }; + } + } +} diff --git a/Application/EdFi.AdminConsole.InstanceMgrWorker.Provisioner/Provisioners/PostgresDatabaseEngineProvider.cs b/Application/EdFi.AdminConsole.InstanceMgrWorker.Provisioner/Provisioners/PostgresDatabaseEngineProvider.cs new file mode 100644 index 000000000..43f9790f8 --- /dev/null +++ b/Application/EdFi.AdminConsole.InstanceMgrWorker.Provisioner/Provisioners/PostgresDatabaseEngineProvider.cs @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: Apache-2.0 +// Licensed to the Ed-Fi Alliance under one or more agreements. +// The Ed-Fi Alliance licenses this file to you under the Apache License, Version 2.0. +// See the LICENSE and NOTICES files in the project root for more information. + +using EdFi.Ods.Common.Configuration; + +namespace EdFi.AdminConsole.InstanceMgrWorker.Configuration.Provisioners +{ + public class PostgresDatabaseEngineProvider : IDatabaseEngineProvider + { + public DatabaseEngine DatabaseEngine { get; } + + public PostgresDatabaseEngineProvider() + { + DatabaseEngine = DatabaseEngine.CreateFromProviderName("Npgsql"); + } + } +} diff --git a/Application/EdFi.AdminConsole.InstanceMgrWorker.Provisioner/Provisioners/PostgresInstanceProvisioner.cs b/Application/EdFi.AdminConsole.InstanceMgrWorker.Provisioner/Provisioners/PostgresInstanceProvisioner.cs new file mode 100644 index 000000000..60e216f9d --- /dev/null +++ b/Application/EdFi.AdminConsole.InstanceMgrWorker.Provisioner/Provisioners/PostgresInstanceProvisioner.cs @@ -0,0 +1,90 @@ +// SPDX-License-Identifier: Apache-2.0 +// Licensed to the Ed-Fi Alliance under one or more agreements. +// The Ed-Fi Alliance licenses this file to you under the Apache License, Version 2.0. +// See the LICENSE and NOTICES files in the project root for more information. + +using System.Data.Common; +using Dapper; +using Microsoft.Extensions.Configuration; +using Npgsql; + +namespace EdFi.AdminConsole.InstanceMgrWorker.Configuration.Provisioners +{ + public class PostgresInstanceProvisioner(IConfiguration configuration, + IMgrWorkerConfigConnectionStringsProvider connectionStringsProvider, IMgrWorkerIDatabaseNameBuilder databaseNameBuilder) : InstanceProvisionerBase(configuration, connectionStringsProvider, databaseNameBuilder) + { + public override async Task RenameDbInstancesAsync(string oldName, string newName) + { + using var conn = CreateConnection(); + string sql = $"SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname='{oldName}';"; + + await conn.ExecuteAsync(sql, commandTimeout: CommandTimeout) + .ConfigureAwait(false); + + sql = $"ALTER DATABASE \"{oldName}\" RENAME TO \"{newName}\";"; + + await conn.ExecuteAsync(sql, commandTimeout: CommandTimeout) + .ConfigureAwait(false); + } + + public override async Task DeleteDbInstancesAsync(params string[] deletedClientKeys) + { + using var conn = CreateConnection(); + foreach (string key in deletedClientKeys) + { + await conn.ExecuteAsync( + $@"SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname='{_databaseNameBuilder.OdsDatabaseName(_tenant, key)}';"); + + await conn.ExecuteAsync( + $@"DROP DATABASE IF EXISTS ""{_databaseNameBuilder.OdsDatabaseName(_tenant, key)}"";", + commandTimeout: CommandTimeout) + .ConfigureAwait(false); + } + } + + public override async Task CopyDbInstanceAsync(string originalDatabaseName, string newDatabaseName) + { + using var conn = CreateConnection(); + string sql = @$"SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname='{originalDatabaseName}';"; + await conn.ExecuteAsync(sql, commandTimeout: CommandTimeout).ConfigureAwait(false); + + sql = @$"CREATE DATABASE ""{newDatabaseName}"" TEMPLATE ""{originalDatabaseName}"""; + await conn.ExecuteAsync(sql, commandTimeout: CommandTimeout).ConfigureAwait(false); + } + + protected override DbConnection CreateConnection() => new NpgsqlConnection(ConnectionString); + + public override async Task GetDbInstanceStatusAsync(string clientKey) + { + using var conn = CreateConnection(); + var results = await conn.QueryAsync( + $"SELECT datname as Name, 0 as Code, 'ONLINE' Description FROM pg_database WHERE datname = \'{_databaseNameBuilder.OdsDatabaseName(_tenant, clientKey)}\';", + commandTimeout: CommandTimeout) + .ConfigureAwait(false); + + return results.SingleOrDefault() ?? InstanceStatus.ErrorStatus(); + } + + public override async Task GetInstancesDatabasesAsync() + { + using var conn = CreateConnection(); + var results = await conn.QueryAsync( + $"SELECT datname as name FROM pg_database WHERE datname like \'{_databaseNameBuilder.OdsDatabaseName(_tenant, "%")}\';", + commandTimeout: CommandTimeout) + .ConfigureAwait(false); + + return results.ToArray(); + } + + public override async Task CheckDatabaseExists(string instanceName) + { + using var conn = CreateConnection(); + var results = await conn.QueryAsync( + $"SELECT datname as name FROM pg_database WHERE datname like \'{_databaseNameBuilder.OdsDatabaseName(_tenant, instanceName)}\';", + commandTimeout: CommandTimeout) + .ConfigureAwait(false); + + return (results?.ToArray().Length ?? 0) > 0; + } + } +} diff --git a/Application/EdFi.AdminConsole.InstanceMgrWorker.Provisioner/Provisioners/SqlServerDatabaseEngineProvider.cs b/Application/EdFi.AdminConsole.InstanceMgrWorker.Provisioner/Provisioners/SqlServerDatabaseEngineProvider.cs new file mode 100644 index 000000000..9247f5aee --- /dev/null +++ b/Application/EdFi.AdminConsole.InstanceMgrWorker.Provisioner/Provisioners/SqlServerDatabaseEngineProvider.cs @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: Apache-2.0 +// Licensed to the Ed-Fi Alliance under one or more agreements. +// The Ed-Fi Alliance licenses this file to you under the Apache License, Version 2.0. +// See the LICENSE and NOTICES files in the project root for more information. + +using EdFi.Ods.Common.Configuration; + +namespace EdFi.AdminConsole.InstanceMgrWorker.Configuration.Provisioners +{ + public class SqlServerDatabaseEngineProvider : IDatabaseEngineProvider + { + public DatabaseEngine DatabaseEngine { get; } + + public SqlServerDatabaseEngineProvider() + { + DatabaseEngine = DatabaseEngine.CreateFromProviderName("System.Data.SqlClient"); + } + } +} diff --git a/Application/EdFi.AdminConsole.InstanceMgrWorker.Provisioner/Provisioners/SqlServerInstanceProvisioner.cs b/Application/EdFi.AdminConsole.InstanceMgrWorker.Provisioner/Provisioners/SqlServerInstanceProvisioner.cs new file mode 100644 index 000000000..15a50ab4e --- /dev/null +++ b/Application/EdFi.AdminConsole.InstanceMgrWorker.Provisioner/Provisioners/SqlServerInstanceProvisioner.cs @@ -0,0 +1,229 @@ +// SPDX-License-Identifier: Apache-2.0 +// Licensed to the Ed-Fi Alliance under one or more agreements. +// The Ed-Fi Alliance licenses this file to you under the Apache License, Version 2.0. +// See the LICENSE and NOTICES files in the project root for more information. + +using System.Data.Common; +using System.Runtime.InteropServices; +using Dapper; +using log4net; +using Microsoft.Data.SqlClient; +using Microsoft.Extensions.Configuration; + +namespace EdFi.AdminConsole.InstanceMgrWorker.Configuration.Provisioners; + +public class SqlServerInstanceProvisioner(IConfiguration configuration, + IMgrWorkerConfigConnectionStringsProvider connectionStringsProvider, IMgrWorkerIDatabaseNameBuilder databaseNameBuilder) : InstanceProvisionerBase(configuration, connectionStringsProvider, databaseNameBuilder) +{ + private readonly ILog _logger = LogManager.GetLogger(typeof(SqlServerInstanceProvisioner)); + private SqlServerHostPlatform? _sqlServerHostPlatform; + private readonly string _sqlServerBakFile = configuration.GetSection("AppSettings:SqlServerBakFile").Value ?? string.Empty; + + public override async Task CheckDatabaseExists(string instanceName) + { + using var conn = CreateConnection(); + var results = await conn.QueryAsync( + $"SELECT name FROM sys.databases WHERE name like @DbName;", + new { DbName = _databaseNameBuilder.OdsDatabaseName(_tenant, instanceName) }, commandTimeout: CommandTimeout) + .ConfigureAwait(false); + + return (results?.ToArray().Length ?? 0) > 0; + } + + public override async Task CopyDbInstanceAsync(string originalDatabaseName, string newDatabaseName) + { + using var conn = CreateConnection(); + await conn.OpenAsync(); + + string sqlServerBakDirectoryMessage = $"backup directory = {_sqlServerBakFile}"; + _logger.Debug(sqlServerBakDirectoryMessage); + + string backup = _sqlServerBakFile; + + string sqlServerBakFileMessage = $"backup file = {_sqlServerBakFile}"; + _logger.Debug(sqlServerBakFileMessage); + + var sqlFileInfo = await GetDatabaseFilesAsync(newDatabaseName) + .ConfigureAwait(false); + + await Restore() + .ConfigureAwait(false); + + // NOTE: these helper functions are using the same connection now. + async Task Restore() + { + string logicalNameForRows = "", logicalNameForLog = ""; + + string restoringFilesFromMessage = $"restoring files from {backup}."; + _logger.Debug(restoringFilesFromMessage); + + using (var reader = await conn.ExecuteReaderAsync($@"RESTORE FILELISTONLY FROM DISK = '{backup}';", commandTimeout: CommandTimeout) + .ConfigureAwait(false)) + { + while (await reader.ReadAsync().ConfigureAwait(false)) + { + string logicalName = reader.GetString(0); + string Type = reader.GetString(2); + if (Type.Equals(LogicalNameType.D.ToString(), StringComparison.InvariantCultureIgnoreCase)) + { + logicalNameForRows = logicalName; + } + else if (Type.Equals(LogicalNameType.L.ToString(), StringComparison.InvariantCultureIgnoreCase)) + { + logicalNameForLog = logicalName; + } + } + + string logicalNameForRowsMessage = $"logical name for Rows Type = {logicalNameForRows}"; + _logger.Debug(logicalNameForRowsMessage); + string logicalNameForLogMessage = $"logical name for Log Type = {logicalNameForLog}"; + _logger.Debug(logicalNameForLogMessage); + } + + string restoringDatabaseMessage = $"Restoring database {newDatabaseName} from {backup}"; + _logger.Debug(restoringDatabaseMessage); + + await conn.ExecuteAsync( + $@"RESTORE DATABASE [{newDatabaseName}] FROM DISK = '{backup}' WITH REPLACE, MOVE '{logicalNameForRows}' TO '{sqlFileInfo.Data}', MOVE '{logicalNameForLog}' TO '{sqlFileInfo.Log}';", commandTimeout: CommandTimeout) + .ConfigureAwait(false); + + var changeLogicalDataName = $"ALTER DATABASE[{newDatabaseName}] MODIFY FILE(NAME='{logicalNameForRows}', NEWNAME='{newDatabaseName}')"; + await conn.ExecuteAsync(changeLogicalDataName, commandTimeout: CommandTimeout) + .ConfigureAwait(false); + + var changeLogicalLogName = $"ALTER DATABASE[{newDatabaseName}] MODIFY FILE(NAME='{logicalNameForLog}', NEWNAME='{newDatabaseName}_log')"; + await conn.ExecuteAsync(changeLogicalLogName, commandTimeout: CommandTimeout) + .ConfigureAwait(false); + } + + async Task GetDatabaseFilesAsync(string newName) + { + var hostPlatform = await GetSqlServerHostPlatform(); + + if (hostPlatform == null) + throw new InvalidOperationException(); + else + { + if (hostPlatform.OsPlatform.Equals(OSPlatform.Windows)) + { + var sqlData = $"SELECT physical_name AS DefaultDataPath FROM sys.master_files WHERE type = {(int)DataPathType.Data} AND database_id = 1;"; + var sqlLog = $"SELECT physical_name AS DefaultLogPath FROM sys.master_files WHERE type = {(int)DataPathType.Log} AND database_id = 1;"; + + string? fullPathData = await conn.ExecuteScalarAsync(sqlData, commandTimeout: CommandTimeout) + .ConfigureAwait(false); + + string? fullPathLog = await conn.ExecuteScalarAsync(sqlLog, commandTimeout: CommandTimeout) + .ConfigureAwait(false); + + return new SqlFileInfo + { + Data = fullPathData?.Replace("master", newName), + Log = fullPathLog?.Replace("mastlog", $"{newName}_Log"), + }; + } + else if (hostPlatform.OsPlatform.Equals(OSPlatform.Linux)) + { + return new SqlFileInfo + { + Data = $"/var/opt/mssql/data/{newName}.mdf", + Log = $"/var/opt/mssql/data/{newName}.ldf" + }; + } + else + throw new InvalidOperationException(); + } + } + } + + public override async Task DeleteDbInstancesAsync(params string[] deletedClientKeys) + { + using var conn = CreateConnection(); + foreach (string key in deletedClientKeys) + { + await conn.ExecuteAsync($@" + IF EXISTS (SELECT name from sys.databases WHERE (name = '{_databaseNameBuilder.OdsDatabaseName(_tenant, key)}')) + BEGIN + ALTER DATABASE [{_databaseNameBuilder.OdsDatabaseName(_tenant, key)}] SET SINGLE_USER WITH ROLLBACK IMMEDIATE; + DROP DATABASE [{_databaseNameBuilder.OdsDatabaseName(_tenant, key)}]; + END; + ", commandTimeout: CommandTimeout) + .ConfigureAwait(false); + } + } + + public override Task GetDbInstanceStatusAsync(string clientKey) + { + throw new NotImplementedException(); + } + + public override Task GetInstancesDatabasesAsync() + { + throw new NotImplementedException(); + } + + public override async Task RenameDbInstancesAsync(string oldName, string newName) + { + using var conn = CreateConnection(); + await conn.ExecuteAsync($"ALTER DATABASE {oldName} MODIFY Name = {newName};") + .ConfigureAwait(false); + } + + protected override DbConnection CreateConnection() => new SqlConnection(ConnectionString); + + private async Task GetSqlServerHostPlatform() + { + if (_sqlServerHostPlatform is null) + { + using var conn = CreateConnection(); + // Get SQL Server OS; sys.dm_os_host_info was introduced in SQL Server 2017 (alongside Linux support) + // if the table doesn't exist we can assume that the OS is Windows + + const string Windows = "Windows"; + + var getHostPlatformSql = $"IF OBJECT_ID('sys.dm_os_host_info') IS NOT NULL SELECT host_platform FROM sys.dm_os_host_info ELSE SELECT '{Windows}'"; + + string? hostPlatform = await conn.ExecuteScalarAsync(getHostPlatformSql, commandTimeout: CommandTimeout) + .ConfigureAwait(false); + + var isWindows = !(hostPlatform is not null) || hostPlatform.Equals(Windows, StringComparison.InvariantCultureIgnoreCase); + + _sqlServerHostPlatform = new SqlServerHostPlatform() + { + OsPlatform = isWindows ? OSPlatform.Windows : OSPlatform.Linux, + DirectorySeparatorChar = isWindows ? '\\' : '/', + VolumeSeparatorChar = isWindows ? ':' : '/' + }; + } + + return _sqlServerHostPlatform; + } + + private sealed class SqlFileInfo + { + public string? Data { get; set; } + + public string? Log { get; set; } + } + + private sealed class SqlServerHostPlatform + { + public OSPlatform OsPlatform { get; set; } + + public char DirectorySeparatorChar { get; set; } + + public char VolumeSeparatorChar { get; set; } + } + + private enum DataPathType + { + Data = 0, + Log = 1 + } + + private enum LogicalNameType + { + D, + L + } +} + diff --git a/Application/EdFi.AdminConsole.InstanceMgrWorker.Provisioner/results.sarif b/Application/EdFi.AdminConsole.InstanceMgrWorker.Provisioner/results.sarif new file mode 100644 index 000000000..cca604a89 --- /dev/null +++ b/Application/EdFi.AdminConsole.InstanceMgrWorker.Provisioner/results.sarif @@ -0,0 +1,21346 @@ +{ + "$schema": "http://json.schemastore.org/sarif-2.1.0", + "version": "2.1.0", + "runs": [ + { + "results": [ + { + "ruleId": "CS8619", + "ruleIndex": 783, + "level": "error", + "message": { + "text": "Nullability of reference types in value of type 'Dictionary' doesn't match target type 'IDictionary'." + }, + "suppressions": [ + { + "kind": "inSource", + "properties": { + "suppressionType": "Pragma Directive" + } + } + ], + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "file:///C:/GAP/EdFi/AdminConsole/development/Ed-Fi-Admin-Console-Instance-Management-Worker-Process/src/EdFi.AdminConsole.InstanceMgrWorker.Provisioner/Provisioners/ConfigConnectionStringsProvider.cs" + }, + "region": { + "startLine": 23, + "startColumn": 28, + "endLine": 25, + "endColumn": 64 + } + } + } + ] + }, + { + "ruleId": "CS8619", + "ruleIndex": 783, + "level": "error", + "message": { + "text": "Nullability of reference types in value of type 'Dictionary' doesn't match target type 'IDictionary'." + }, + "suppressions": [ + { + "kind": "inSource", + "properties": { + "suppressionType": "Pragma Directive" + } + } + ], + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "file:///C:/GAP/EdFi/AdminConsole/development/Ed-Fi-Admin-Console-Instance-Management-Worker-Process/src/EdFi.AdminConsole.InstanceMgrWorker.Provisioner/Provisioners/ConfigConnectionStringsProvider.cs" + }, + "region": { + "startLine": 27, + "startColumn": 28, + "endLine": 29, + "endColumn": 64 + } + } + } + ] + }, + { + "ruleId": "S112", + "ruleIndex": 332, + "level": "note", + "message": { + "text": "'System.Exception' should not be thrown by user code." + }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "file:///C:/GAP/EdFi/AdminConsole/development/Ed-Fi-Admin-Console-Instance-Management-Worker-Process/src/EdFi.AdminConsole.InstanceMgrWorker.Provisioner/Provisioners/InstanceProvisionerBase.cs" + }, + "region": { + "startLine": 97, + "startColumn": 27, + "endLine": 97, + "endColumn": 75 + } + } + } + ], + "properties": { + "warningLevel": 1 + } + }, + { + "ruleId": "S112", + "ruleIndex": 332, + "level": "note", + "message": { + "text": "'System.Exception' should not be thrown by user code." + }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "file:///C:/GAP/EdFi/AdminConsole/development/Ed-Fi-Admin-Console-Instance-Management-Worker-Process/src/EdFi.AdminConsole.InstanceMgrWorker.Provisioner/Provisioners/SqlServerInstanceProvisioner.cs" + }, + "region": { + "startLine": 152, + "startColumn": 23, + "endLine": 152, + "endColumn": 47 + } + } + } + ], + "properties": { + "warningLevel": 1 + } + } + ], + "properties": { + "analyzerExecutionTime": "5.893" + }, + "tool": { + "driver": { + "name": "Microsoft (R) Visual C# Compiler", + "version": "4.12.0-3.24631.1 (da7c6c42)", + "dottedQuadFileVersion": "4.12.0.0", + "semanticVersion": "4.12.0", + "language": "en-US", + "rules": [ + { + "id": "CA1000", + "shortDescription": { + "text": "Do not declare static members on generic types" + }, + "fullDescription": { + "text": "When a static member of a generic type is called, the type argument must be specified for the type. When a generic instance member that does not support inference is called, the type argument must be specified for the member. In these two cases, the syntax for specifying the type argument is different and easily confused." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1000", + "properties": { + "category": "Design", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1001", + "shortDescription": { + "text": "Types that own disposable fields should be disposable" + }, + "fullDescription": { + "text": "A class declares and implements an instance field that is a System.IDisposable type, and the class does not implement IDisposable. A class that declares an IDisposable field indirectly owns an unmanaged resource and should implement the IDisposable interface." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1001", + "properties": { + "category": "Design", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1002", + "shortDescription": { + "text": "Do not expose generic lists" + }, + "fullDescription": { + "text": "System.Collections.Generic.List is a generic collection that's designed for performance and not inheritance. List does not contain virtual members that make it easier to change the behavior of an inherited class." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1002", + "properties": { + "category": "Design", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1003", + "shortDescription": { + "text": "Use generic event handler instances" + }, + "fullDescription": { + "text": "A type contains a delegate that returns void, whose signature contains two parameters (the first an object and the second a type that is assignable to EventArgs), and the containing assembly targets Microsoft .NET Framework?2.0." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1003", + "properties": { + "category": "Design", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1005", + "shortDescription": { + "text": "Avoid excessive parameters on generic types" + }, + "fullDescription": { + "text": "The more type parameters a generic type contains, the more difficult it is to know and remember what each type parameter represents." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1005", + "properties": { + "category": "Design", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry" + ] + } + }, + { + "id": "CA1008", + "shortDescription": { + "text": "Enums should have zero value" + }, + "fullDescription": { + "text": "The default value of an uninitialized enumeration, just as other value types, is zero. A nonflags-attributed enumeration should define a member by using the value of zero so that the default value is a valid value of the enumeration. If an enumeration that has the FlagsAttribute attribute applied defines a zero-valued member, its name should be \"\"None\"\" to indicate that no values have been set in the enumeration." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1008", + "properties": { + "category": "Design", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode", + "RuleRename" + ] + } + }, + { + "id": "CA1010", + "shortDescription": { + "text": "Generic interface should also be implemented" + }, + "fullDescription": { + "text": "To broaden the usability of a type, implement one of the generic interfaces. This is especially true for collections as they can then be used to populate generic collection types." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1010", + "properties": { + "category": "Design", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1012", + "shortDescription": { + "text": "Abstract types should not have public constructors" + }, + "fullDescription": { + "text": "Constructors on abstract types can be called only by derived types. Because public constructors create instances of a type, and you cannot create instances of an abstract type, an abstract type that has a public constructor is incorrectly designed." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1012", + "properties": { + "category": "Design", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1014", + "shortDescription": { + "text": "Mark assemblies with CLSCompliant" + }, + "fullDescription": { + "text": "The Common Language Specification (CLS) defines naming restrictions, data types, and rules to which assemblies must conform if they will be used across programming languages. Good design dictates that all assemblies explicitly indicate CLS compliance by using CLSCompliantAttribute . If this attribute is not present on an assembly, the assembly is not compliant." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1014", + "properties": { + "category": "Design", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "0.022", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "CompilationEnd" + ] + } + }, + { + "id": "CA1016", + "shortDescription": { + "text": "Mark assemblies with assembly version" + }, + "fullDescription": { + "text": "The .NET Framework uses the version number to uniquely identify an assembly, and to bind to types in strongly named assemblies. The version number is used together with version and publisher policy. By default, applications run only with the assembly version with which they were built." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1016", + "properties": { + "category": "Design", + "executionTimeInSeconds": "0.022", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode", + "CompilationEnd" + ] + } + }, + { + "id": "CA1017", + "shortDescription": { + "text": "Mark assemblies with ComVisible" + }, + "fullDescription": { + "text": "ComVisibleAttribute determines how COM clients access managed code. Good design dictates that assemblies explicitly indicate COM visibility. COM visibility can be set for the whole assembly and then overridden for individual types and type members. If this attribute is not present, the contents of the assembly are visible to COM clients." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1017", + "properties": { + "category": "Design", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "CompilationEnd" + ] + } + }, + { + "id": "CA1018", + "shortDescription": { + "text": "Mark attributes with AttributeUsageAttribute" + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1018", + "properties": { + "category": "Design", + "executionTimeInSeconds": "0.008", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1019", + "shortDescription": { + "text": "Define accessors for attribute arguments" + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1019", + "properties": { + "category": "Design", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1021", + "shortDescription": { + "text": "Avoid out parameters" + }, + "fullDescription": { + "text": "Passing types by reference (using 'out' or 'ref') requires experience with pointers, understanding how value types and reference types differ, and handling methods with multiple return values. Also, the difference between 'out' and 'ref' parameters is not widely understood." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1021", + "properties": { + "category": "Design", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry" + ] + } + }, + { + "id": "CA1024", + "shortDescription": { + "text": "Use properties where appropriate" + }, + "fullDescription": { + "text": "A public or protected method has a name that starts with \"\"Get\"\", takes no parameters, and returns a value that is not an array. The method might be a good candidate to become a property." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1024", + "properties": { + "category": "Design", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1027", + "shortDescription": { + "text": "Mark enums with FlagsAttribute" + }, + "fullDescription": { + "text": "An enumeration is a value type that defines a set of related named constants. Apply FlagsAttribute to an enumeration when its named constants can be meaningfully combined." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1027", + "properties": { + "category": "Design", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1028", + "shortDescription": { + "text": "Enum Storage should be Int32" + }, + "fullDescription": { + "text": "An enumeration is a value type that defines a set of related named constants. By default, the System.Int32 data type is used to store the constant value. Although you can change this underlying type, it is not required or recommended for most scenarios." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1028", + "properties": { + "category": "Design", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1030", + "shortDescription": { + "text": "Use events where appropriate" + }, + "fullDescription": { + "text": "This rule detects methods that have names that ordinarily would be used for events. If a method is called in response to a clearly defined state change, the method should be invoked by an event handler. Objects that call the method should raise events instead of calling the method directly." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1030", + "properties": { + "category": "Design", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1031", + "shortDescription": { + "text": "Do not catch general exception types" + }, + "fullDescription": { + "text": "A general exception such as System.Exception or System.SystemException or a disallowed exception type is caught in a catch statement, or a general catch clause is used. General and disallowed exceptions should not be caught." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1031", + "properties": { + "category": "Design", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1032", + "shortDescription": { + "text": "Implement standard exception constructors" + }, + "fullDescription": { + "text": "Failure to provide the full set of constructors can make it difficult to correctly handle exceptions." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1032", + "properties": { + "category": "Design", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1033", + "shortDescription": { + "text": "Interface methods should be callable by child types" + }, + "fullDescription": { + "text": "An unsealed externally visible type provides an explicit method implementation of a public interface and does not provide an alternative externally visible method that has the same name." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1033", + "properties": { + "category": "Design", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1034", + "shortDescription": { + "text": "Nested types should not be visible" + }, + "fullDescription": { + "text": "A nested type is a type that is declared in the scope of another type. Nested types are useful to encapsulate private implementation details of the containing type. Used for this purpose, nested types should not be externally visible." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1034", + "properties": { + "category": "Design", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1036", + "shortDescription": { + "text": "Override methods on comparable types" + }, + "fullDescription": { + "text": "A public or protected type implements the System.IComparable interface. It does not override Object.Equals nor does it overload the language-specific operator for equality, inequality, less than, less than or equal, greater than or greater than or equal." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1036", + "properties": { + "category": "Design", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1040", + "shortDescription": { + "text": "Avoid empty interfaces" + }, + "fullDescription": { + "text": "Interfaces define members that provide a behavior or usage contract. The functionality that is described by the interface can be adopted by any type, regardless of where the type appears in the inheritance hierarchy. A type implements an interface by providing implementations for the members of the interface. An empty interface does not define any members; therefore, it does not define a contract that can be implemented." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1040", + "properties": { + "category": "Design", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1041", + "shortDescription": { + "text": "Provide ObsoleteAttribute message" + }, + "fullDescription": { + "text": "A type or member is marked by using a System.ObsoleteAttribute attribute that does not have its ObsoleteAttribute.Message property specified. When a type or member that is marked by using ObsoleteAttribute is compiled, the Message property of the attribute is displayed. This gives the user information about the obsolete type or member." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1041", + "properties": { + "category": "Design", + "executionTimeInSeconds": "0.079", + "executionTimeInPercentage": "1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1043", + "shortDescription": { + "text": "Use Integral Or String Argument For Indexers" + }, + "fullDescription": { + "text": "Indexers, that is, indexed properties, should use integer or string types for the index. These types are typically used for indexing data structures and increase the usability of the library. Use of the Object type should be restricted to those cases where the specific integer or string type cannot be specified at design time. If the design requires other types for the index, reconsider whether the type represents a logical data store. If it does not represent a logical data store, use a method." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1043", + "properties": { + "category": "Design", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1044", + "shortDescription": { + "text": "Properties should not be write only" + }, + "fullDescription": { + "text": "Although it is acceptable and often necessary to have a read-only property, the design guidelines prohibit the use of write-only properties. This is because letting a user set a value, and then preventing the user from viewing that value, does not provide any security. Also, without read access, the state of shared objects cannot be viewed, which limits their usefulness." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1044", + "properties": { + "category": "Design", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1045", + "shortDescription": { + "text": "Do not pass types by reference" + }, + "fullDescription": { + "text": "Passing types by reference (using out or ref) requires experience with pointers, understanding how value types and reference types differ, and handling methods that have multiple return values. Also, the difference between out and ref parameters is not widely understood." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1045", + "properties": { + "category": "Design", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry" + ] + } + }, + { + "id": "CA1046", + "shortDescription": { + "text": "Do not overload equality operator on reference types" + }, + "fullDescription": { + "text": "For reference types, the default implementation of the equality operator is almost always correct. By default, two references are equal only if they point to the same object. If the operator is providing meaningful value equality, the type should implement the generic 'System.IEquatable' interface." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1046", + "properties": { + "category": "Design", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1050", + "shortDescription": { + "text": "Declare types in namespaces" + }, + "fullDescription": { + "text": "Types are declared in namespaces to prevent name collisions and as a way to organize related types in an object hierarchy." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1050", + "properties": { + "category": "Design", + "executionTimeInSeconds": "0.003", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1051", + "shortDescription": { + "text": "Do not declare visible instance fields" + }, + "fullDescription": { + "text": "The primary use of a field should be as an implementation detail. Fields should be private or internal and should be exposed by using properties." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1051", + "properties": { + "category": "Design", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1052", + "shortDescription": { + "text": "Static holder types should be Static or NotInheritable" + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1052", + "properties": { + "category": "Design", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1054", + "shortDescription": { + "text": "URI-like parameters should not be strings" + }, + "fullDescription": { + "text": "This rule assumes that the parameter represents a Uniform Resource Identifier (URI). A string representation or a URI is prone to parsing and encoding errors, and can lead to security vulnerabilities. 'System.Uri' class provides these services in a safe and secure manner." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1054", + "properties": { + "category": "Design", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1055", + "shortDescription": { + "text": "URI-like return values should not be strings" + }, + "fullDescription": { + "text": "This rule assumes that the method returns a URI. A string representation of a URI is prone to parsing and encoding errors, and can lead to security vulnerabilities. The System.Uri class provides these services in a safe and secure manner." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1055", + "properties": { + "category": "Design", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1056", + "shortDescription": { + "text": "URI-like properties should not be strings" + }, + "fullDescription": { + "text": "This rule assumes that the property represents a Uniform Resource Identifier (URI). A string representation of a URI is prone to parsing and encoding errors, and can lead to security vulnerabilities. The System.Uri class provides these services in a safe and secure manner." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1056", + "properties": { + "category": "Design", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1058", + "shortDescription": { + "text": "Types should not extend certain base types" + }, + "fullDescription": { + "text": "An externally visible type extends certain base types. Use one of the alternatives." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1058", + "properties": { + "category": "Design", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1060", + "shortDescription": { + "text": "Move pinvokes to native methods class" + }, + "fullDescription": { + "text": "Platform Invocation methods, such as those that are marked by using the System.Runtime.InteropServices.DllImportAttribute attribute, or methods that are defined by using the Declare keyword in Visual Basic, access unmanaged code. These methods should be of the NativeMethods, SafeNativeMethods, or UnsafeNativeMethods class." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1060", + "properties": { + "category": "Design", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry" + ] + } + }, + { + "id": "CA1061", + "shortDescription": { + "text": "Do not hide base class methods" + }, + "fullDescription": { + "text": "A method in a base type is hidden by an identically named method in a derived type when the parameter signature of the derived method differs only by types that are more weakly derived than the corresponding types in the parameter signature of the base method." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1061", + "properties": { + "category": "Design", + "executionTimeInSeconds": "0.005", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1062", + "shortDescription": { + "text": "Validate arguments of public methods" + }, + "fullDescription": { + "text": "An externally visible method dereferences one of its reference arguments without verifying whether that argument is 'null' ('Nothing' in Visual Basic). All reference arguments that are passed to externally visible methods should be checked against 'null'. If appropriate, throw an 'ArgumentNullException' when the argument is 'null'. If the method is designed to be called only by known assemblies, you should make the method internal." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1062", + "properties": { + "category": "Design", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Dataflow", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1063", + "shortDescription": { + "text": "Implement IDisposable Correctly" + }, + "fullDescription": { + "text": "All IDisposable types should implement the Dispose pattern correctly." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1063", + "properties": { + "category": "Design", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1064", + "shortDescription": { + "text": "Exceptions should be public" + }, + "fullDescription": { + "text": "An internal exception is visible only inside its own internal scope. After the exception falls outside the internal scope, only the base exception can be used to catch the exception. If the internal exception is inherited from T:System.Exception, T:System.SystemException, or T:System.ApplicationException, the external code will not have sufficient information to know what to do with the exception." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1064", + "properties": { + "category": "Design", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1065", + "shortDescription": { + "text": "Do not raise exceptions in unexpected locations" + }, + "fullDescription": { + "text": "A method that is not expected to throw exceptions throws an exception." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1065", + "properties": { + "category": "Design", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1066", + "shortDescription": { + "text": "Implement IEquatable when overriding Object.Equals" + }, + "fullDescription": { + "text": "When a type T overrides Object.Equals(object), the implementation must cast the object argument to the correct type T before performing the comparison. If the type implements IEquatable, and therefore offers the method T.Equals(T), and if the argument is known at compile time to be of type T, then the compiler can call IEquatable.Equals(T) instead of Object.Equals(object), and no cast is necessary, improving performance." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1066", + "properties": { + "category": "Design", + "executionTimeInSeconds": "0.008", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1067", + "shortDescription": { + "text": "Override Object.Equals(object) when implementing IEquatable" + }, + "fullDescription": { + "text": "When a type T implements the interface IEquatable, it suggests to a user who sees a call to the Equals method in source code that an instance of the type can be equated with an instance of any other type. The user might be confused if their attempt to equate the type with an instance of another type fails to compile. This violates the \"principle of least surprise\"." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1067", + "properties": { + "category": "Design", + "executionTimeInSeconds": "0.008", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1068", + "shortDescription": { + "text": "CancellationToken parameters must come last" + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1068", + "properties": { + "category": "Design", + "executionTimeInSeconds": "0.013", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1069", + "shortDescription": { + "text": "Enums values should not be duplicated" + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1069", + "properties": { + "category": "Design", + "executionTimeInSeconds": "0.070", + "executionTimeInPercentage": "1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1070", + "shortDescription": { + "text": "Do not declare event fields as virtual" + }, + "fullDescription": { + "text": "Do not declare virtual events in a base class. Overridden events in a derived class have undefined behavior. The C# compiler does not handle this correctly and it is unpredictable whether a subscriber to the derived event will actually be subscribing to the base class event." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1070", + "properties": { + "category": "Design", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1200", + "shortDescription": { + "text": "Avoid using cref tags with a prefix" + }, + "fullDescription": { + "text": "Use of cref tags with prefixes should be avoided, since it prevents the compiler from verifying references and the IDE from updating references during refactorings. It is permissible to suppress this error at a single documentation site if the cref must use a prefix because the type being mentioned is not findable by the compiler. For example, if a cref is mentioning a special attribute in the full framework but you're in a file that compiles against the portable framework, or if you want to reference a type at higher layer of Roslyn, you should suppress the error. You should not suppress the error just because you want to take a shortcut and avoid using the full syntax." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1200", + "properties": { + "category": "Documentation", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1303", + "shortDescription": { + "text": "Do not pass literals as localized parameters" + }, + "fullDescription": { + "text": "A method passes a string literal as a parameter to a constructor or method in the .NET Framework class library and that string should be localizable. To fix a violation of this rule, replace the string literal with a string retrieved through an instance of the ResourceManager class." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1303", + "properties": { + "category": "Globalization", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Dataflow", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1304", + "shortDescription": { + "text": "Specify CultureInfo" + }, + "fullDescription": { + "text": "A method or constructor calls a member that has an overload that accepts a System.Globalization.CultureInfo parameter, and the method or constructor does not call the overload that takes the CultureInfo parameter. When a CultureInfo or System.IFormatProvider object is not supplied, the default value that is supplied by the overloaded member might not have the effect that you want in all locales. If the result will be displayed to the user, specify 'CultureInfo.CurrentCulture' as the 'CultureInfo' parameter. Otherwise, if the result will be stored and accessed by software, such as when it is persisted to disk or to a database, specify 'CultureInfo.InvariantCulture'." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1304", + "properties": { + "category": "Globalization", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1305", + "shortDescription": { + "text": "Specify IFormatProvider" + }, + "fullDescription": { + "text": "A method or constructor calls one or more members that have overloads that accept a System.IFormatProvider parameter, and the method or constructor does not call the overload that takes the IFormatProvider parameter. When a System.Globalization.CultureInfo or IFormatProvider object is not supplied, the default value that is supplied by the overloaded member might not have the effect that you want in all locales. If the result will be based on the input from/output displayed to the user, specify 'CultureInfo.CurrentCulture' as the 'IFormatProvider'. Otherwise, if the result will be stored and accessed by software, such as when it is loaded from disk/database and when it is persisted to disk/database, specify 'CultureInfo.InvariantCulture'." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1305", + "properties": { + "category": "Globalization", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1307", + "shortDescription": { + "text": "Specify StringComparison for clarity" + }, + "fullDescription": { + "text": "A string comparison operation uses a method overload that does not set a StringComparison parameter. It is recommended to use the overload with StringComparison parameter for clarity of intent. If the result will be displayed to the user, such as when sorting a list of items for display in a list box, specify 'StringComparison.CurrentCulture' or 'StringComparison.CurrentCultureIgnoreCase' as the 'StringComparison' parameter. If comparing case-insensitive identifiers, such as file paths, environment variables, or registry keys and values, specify 'StringComparison.OrdinalIgnoreCase'. Otherwise, if comparing case-sensitive identifiers, specify 'StringComparison.Ordinal'." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1307", + "properties": { + "category": "Globalization", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1308", + "shortDescription": { + "text": "Normalize strings to uppercase" + }, + "fullDescription": { + "text": "Strings should be normalized to uppercase. A small group of characters cannot make a round trip when they are converted to lowercase. To make a round trip means to convert the characters from one locale to another locale that represents character data differently, and then to accurately retrieve the original characters from the converted characters." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1308", + "properties": { + "category": "Globalization", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1309", + "shortDescription": { + "text": "Use ordinal string comparison" + }, + "fullDescription": { + "text": "A string comparison operation that is nonlinguistic does not set the StringComparison parameter to either Ordinal or OrdinalIgnoreCase. By explicitly setting the parameter to either StringComparison.Ordinal or StringComparison.OrdinalIgnoreCase, your code often gains speed, becomes more correct, and becomes more reliable." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1309", + "properties": { + "category": "Globalization", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1310", + "shortDescription": { + "text": "Specify StringComparison for correctness" + }, + "fullDescription": { + "text": "A string comparison operation uses a method overload that does not set a StringComparison parameter, hence its behavior could vary based on the current user's locale settings. It is strongly recommended to use the overload with StringComparison parameter for correctness and clarity of intent. If the result will be displayed to the user, such as when sorting a list of items for display in a list box, specify 'StringComparison.CurrentCulture' or 'StringComparison.CurrentCultureIgnoreCase' as the 'StringComparison' parameter. If comparing case-insensitive identifiers, such as file paths, environment variables, or registry keys and values, specify 'StringComparison.OrdinalIgnoreCase'. Otherwise, if comparing case-sensitive identifiers, specify 'StringComparison.Ordinal'." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1310", + "properties": { + "category": "Globalization", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1311", + "shortDescription": { + "text": "Specify a culture or use an invariant version" + }, + "fullDescription": { + "text": "Specify culture to help avoid accidental implicit dependency on current culture. Using an invariant version yields consistent results regardless of the culture of an application." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1311", + "properties": { + "category": "Globalization", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1401", + "shortDescription": { + "text": "P/Invokes should not be visible" + }, + "fullDescription": { + "text": "A public or protected method in a public type has the System.Runtime.InteropServices.DllImportAttribute attribute (also implemented by the Declare keyword in Visual Basic). Such methods should not be exposed." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1401", + "properties": { + "category": "Interoperability", + "executionTimeInSeconds": "0.008", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1416", + "shortDescription": { + "text": "Validate platform compatibility" + }, + "fullDescription": { + "text": "Using platform dependent API on a component makes the code no longer work across all platforms." + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1416", + "properties": { + "category": "Interoperability", + "executionTimeInSeconds": "0.088", + "executionTimeInPercentage": "1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1417", + "shortDescription": { + "text": "Do not use 'OutAttribute' on string parameters for P/Invokes" + }, + "fullDescription": { + "text": "String parameters passed by value with the 'OutAttribute' can destabilize the runtime if the string is an interned string." + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1417", + "properties": { + "category": "Interoperability", + "executionTimeInSeconds": "0.002", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1418", + "shortDescription": { + "text": "Use valid platform string" + }, + "fullDescription": { + "text": "Platform compatibility analyzer requires a valid platform name and version." + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1418", + "properties": { + "category": "Interoperability", + "executionTimeInSeconds": "0.059", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1419", + "shortDescription": { + "text": "Provide a parameterless constructor that is as visible as the containing type for concrete types derived from 'System.Runtime.InteropServices.SafeHandle'" + }, + "fullDescription": { + "text": "Providing a parameterless constructor that is as visible as the containing type for a type derived from 'System.Runtime.InteropServices.SafeHandle' enables better performance and usage with source-generated interop solutions." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1419", + "properties": { + "category": "Interoperability", + "executionTimeInSeconds": "0.006", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1420", + "shortDescription": { + "text": "Property, type, or attribute requires runtime marshalling" + }, + "fullDescription": { + "text": "Using features that require runtime marshalling when runtime marshalling is disabled will result in runtime exceptions." + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1420", + "properties": { + "category": "Interoperability", + "executionTimeInSeconds": "0.009", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1421", + "shortDescription": { + "text": "This method uses runtime marshalling even when the 'DisableRuntimeMarshallingAttribute' is applied" + }, + "fullDescription": { + "text": "This method uses runtime marshalling even when runtime marshalling is disabled, which can cause unexpected behavior differences at runtime due to different expectations of a type's native layout." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1421", + "properties": { + "category": "Interoperability", + "executionTimeInSeconds": "0.009", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1422", + "shortDescription": { + "text": "Validate platform compatibility" + }, + "fullDescription": { + "text": "Using platform dependent API on a component makes the code no longer work across all platforms." + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1422", + "properties": { + "category": "Interoperability", + "executionTimeInSeconds": "0.088", + "executionTimeInPercentage": "1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1501", + "shortDescription": { + "text": "Avoid excessive inheritance" + }, + "fullDescription": { + "text": "Deeply nested type hierarchies can be difficult to follow, understand, and maintain. This rule limits analysis to hierarchies in the same module. To fix a violation of this rule, derive the type from a base type that is less deep in the inheritance hierarchy or eliminate some of the intermediate base types." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1501", + "properties": { + "category": "Maintainability", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "CompilationEnd" + ] + } + }, + { + "id": "CA1502", + "shortDescription": { + "text": "Avoid excessive complexity" + }, + "fullDescription": { + "text": "Cyclomatic complexity measures the number of linearly independent paths through the method, which is determined by the number and complexity of conditional branches. A low cyclomatic complexity generally indicates a method that is easy to understand, test, and maintain. The cyclomatic complexity is calculated from a control flow graph of the method and is given as follows: `cyclomatic complexity = the number of edges - the number of nodes + 1`, where a node represents a logic branch point and an edge represents a line between nodes." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1502", + "properties": { + "category": "Maintainability", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "CompilationEnd" + ] + } + }, + { + "id": "CA1505", + "shortDescription": { + "text": "Avoid unmaintainable code" + }, + "fullDescription": { + "text": "The maintainability index is calculated by using the following metrics: lines of code, program volume, and cyclomatic complexity. Program volume is a measure of the difficulty of understanding of a symbol that is based on the number of operators and operands in the code. Cyclomatic complexity is a measure of the structural complexity of the type or method. A low maintainability index indicates that code is probably difficult to maintain and would be a good candidate to redesign." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1505", + "properties": { + "category": "Maintainability", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "CompilationEnd" + ] + } + }, + { + "id": "CA1506", + "shortDescription": { + "text": "Avoid excessive class coupling" + }, + "fullDescription": { + "text": "This rule measures class coupling by counting the number of unique type references that a symbol contains. Symbols that have a high degree of class coupling can be difficult to maintain. It is a good practice to have types and methods that exhibit low coupling and high cohesion. To fix this violation, try to redesign the code to reduce the number of types to which it is coupled." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1506", + "properties": { + "category": "Maintainability", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "CompilationEnd" + ] + } + }, + { + "id": "CA1507", + "shortDescription": { + "text": "Use nameof to express symbol names" + }, + "fullDescription": { + "text": "Using nameof helps keep your code valid when refactoring." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1507", + "properties": { + "category": "Maintainability", + "executionTimeInSeconds": "0.005", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1508", + "shortDescription": { + "text": "Avoid dead conditional code" + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1508", + "properties": { + "category": "Maintainability", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Dataflow", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1509", + "shortDescription": { + "text": "Invalid entry in code metrics rule specification file" + }, + "fullDescription": { + "text": "Invalid entry in code metrics rule specification file." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1509", + "properties": { + "category": "Maintainability", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "CompilationEnd" + ] + } + }, + { + "id": "CA1510", + "shortDescription": { + "text": "Use ArgumentNullException throw helper" + }, + "fullDescription": { + "text": "Throw helpers are simpler and more efficient than an if block constructing a new exception instance." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1510", + "properties": { + "category": "Maintainability", + "executionTimeInSeconds": "0.007", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1511", + "shortDescription": { + "text": "Use ArgumentException throw helper" + }, + "fullDescription": { + "text": "Throw helpers are simpler and more efficient than an if block constructing a new exception instance." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1511", + "properties": { + "category": "Maintainability", + "executionTimeInSeconds": "0.007", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1512", + "shortDescription": { + "text": "Use ArgumentOutOfRangeException throw helper" + }, + "fullDescription": { + "text": "Throw helpers are simpler and more efficient than an if block constructing a new exception instance." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1512", + "properties": { + "category": "Maintainability", + "executionTimeInSeconds": "0.007", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1513", + "shortDescription": { + "text": "Use ObjectDisposedException throw helper" + }, + "fullDescription": { + "text": "Throw helpers are simpler and more efficient than an if block constructing a new exception instance." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1513", + "properties": { + "category": "Maintainability", + "executionTimeInSeconds": "0.007", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1514", + "shortDescription": { + "text": "Avoid redundant length argument" + }, + "fullDescription": { + "text": "An explicit length calculation can be error-prone and can be avoided when slicing to end of the buffer." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1514", + "properties": { + "category": "Maintainability", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1515", + "shortDescription": { + "text": "Consider making public types internal" + }, + "fullDescription": { + "text": "Unlike a class library, an application's API isn't typically referenced publicly, so types can be marked internal." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1515", + "properties": { + "category": "Maintainability", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1700", + "shortDescription": { + "text": "Do not name enum values 'Reserved'" + }, + "fullDescription": { + "text": "This rule assumes that an enumeration member that has a name that contains \"reserved\" is not currently used but is a placeholder to be renamed or removed in a future version. Renaming or removing a member is a breaking change." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1700", + "properties": { + "category": "Naming", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1707", + "shortDescription": { + "text": "Identifiers should not contain underscores" + }, + "fullDescription": { + "text": "By convention, identifier names do not contain the underscore (_) character. This rule checks namespaces, types, members, and parameters." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1707", + "properties": { + "category": "Naming", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1708", + "shortDescription": { + "text": "Identifiers should differ by more than case" + }, + "fullDescription": { + "text": "Identifiers for namespaces, types, members, and parameters cannot differ only by case because languages that target the common language runtime are not required to be case-sensitive." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1708", + "properties": { + "category": "Naming", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1710", + "shortDescription": { + "text": "Identifiers should have correct suffix" + }, + "fullDescription": { + "text": "By convention, the names of types that extend certain base types or that implement certain interfaces, or types that are derived from these types, have a suffix that is associated with the base type or interface." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1710", + "properties": { + "category": "Naming", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1711", + "shortDescription": { + "text": "Identifiers should not have incorrect suffix" + }, + "fullDescription": { + "text": "By convention, only the names of types that extend certain base types or that implement certain interfaces, or types that are derived from these types, should end with specific reserved suffixes. Other type names should not use these reserved suffixes." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1711", + "properties": { + "category": "Naming", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1712", + "shortDescription": { + "text": "Do not prefix enum values with type name" + }, + "fullDescription": { + "text": "An enumeration's values should not start with the type name of the enumeration." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1712", + "properties": { + "category": "Naming", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1713", + "shortDescription": { + "text": "Events should not have 'Before' or 'After' prefix" + }, + "fullDescription": { + "text": "Event names should describe the action that raises the event. To name related events that are raised in a specific sequence, use the present or past tense to indicate the relative position in the sequence of actions. For example, when naming a pair of events that is raised when closing a resource, you might name it 'Closing' and 'Closed', instead of 'BeforeClose' and 'AfterClose'." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1713", + "properties": { + "category": "Naming", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1715", + "shortDescription": { + "text": "Identifiers should have correct prefix" + }, + "fullDescription": { + "text": "The name of an externally visible interface does not start with an uppercase \"\"I\"\". The name of a generic type parameter on an externally visible type or method does not start with an uppercase \"\"T\"\"." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1715", + "properties": { + "category": "Naming", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1716", + "shortDescription": { + "text": "Identifiers should not match keywords" + }, + "fullDescription": { + "text": "A namespace name or a type name matches a reserved keyword in a programming language. Identifiers for namespaces and types should not match keywords that are defined by languages that target the common language runtime." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1716", + "properties": { + "category": "Naming", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1720", + "shortDescription": { + "text": "Identifier contains type name" + }, + "fullDescription": { + "text": "Names of parameters and members are better used to communicate their meaning than to describe their type, which is expected to be provided by development tools. For names of members, if a data type name must be used, use a language-independent name instead of a language-specific one." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1720", + "properties": { + "category": "Naming", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1721", + "shortDescription": { + "text": "Property names should not match get methods" + }, + "fullDescription": { + "text": "The name of a public or protected member starts with \"\"Get\"\" and otherwise matches the name of a public or protected property. \"\"Get\"\" methods and properties should have names that clearly distinguish their function." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1721", + "properties": { + "category": "Naming", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1724", + "shortDescription": { + "text": "Type names should not match namespaces" + }, + "fullDescription": { + "text": "Type names should not match the names of namespaces that are defined in the .NET Framework class library. Violating this rule can reduce the usability of the library." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1724", + "properties": { + "category": "Naming", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode", + "CompilationEnd" + ] + } + }, + { + "id": "CA1725", + "shortDescription": { + "text": "Parameter names should match base declaration" + }, + "fullDescription": { + "text": "Consistent naming of parameters in an override hierarchy increases the usability of the method overrides. A parameter name in a derived method that differs from the name in the base declaration can cause confusion about whether the method is an override of the base method or a new overload of the method." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1725", + "properties": { + "category": "Naming", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1727", + "shortDescription": { + "text": "Use PascalCase for named placeholders" + }, + "fullDescription": { + "text": "Use PascalCase for named placeholders in the logging message template." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1727", + "properties": { + "category": "Naming", + "executionTimeInSeconds": "0.004", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1802", + "shortDescription": { + "text": "Use literals where appropriate" + }, + "fullDescription": { + "text": "A field is declared static and read-only (Shared and ReadOnly in Visual Basic), and is initialized by using a value that is computable at compile time. Because the value that is assigned to the targeted field is computable at compile time, change the declaration to a const (Const in Visual Basic) field so that the value is computed at compile time instead of at runtime." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1802", + "properties": { + "category": "Performance", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1805", + "shortDescription": { + "text": "Do not initialize unnecessarily" + }, + "fullDescription": { + "text": "The .NET runtime initializes all fields of reference types to their default values before running the constructor. In most cases, explicitly initializing a field to its default value in a constructor is redundant, adding maintenance costs and potentially degrading performance (such as with increased assembly size), and the explicit initialization can be removed. In some cases, such as with static readonly fields that permanently retain their default value, consider instead changing them to be constants or properties." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1805", + "properties": { + "category": "Performance", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1806", + "shortDescription": { + "text": "Do not ignore method results" + }, + "fullDescription": { + "text": "A new object is created but never used; or a method that creates and returns a new string is called and the new string is never used; or a COM or P/Invoke method returns an HRESULT or error code that is never used." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1806", + "properties": { + "category": "Performance", + "executionTimeInSeconds": "0.005", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1810", + "shortDescription": { + "text": "Initialize reference type static fields inline" + }, + "fullDescription": { + "text": "A reference type declares an explicit static constructor. To fix a violation of this rule, initialize all static data when it is declared and remove the static constructor." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1810", + "properties": { + "category": "Performance", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1812", + "shortDescription": { + "text": "Avoid uninstantiated internal classes" + }, + "fullDescription": { + "text": "An instance of an assembly-level type is not created by code in the assembly." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1812", + "properties": { + "category": "Performance", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode", + "CompilationEnd" + ] + } + }, + { + "id": "CA1813", + "shortDescription": { + "text": "Avoid unsealed attributes" + }, + "fullDescription": { + "text": "The .NET Framework class library provides methods for retrieving custom attributes. By default, these methods search the attribute inheritance hierarchy. Sealing the attribute eliminates the search through the inheritance hierarchy and can improve performance." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1813", + "properties": { + "category": "Performance", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1814", + "shortDescription": { + "text": "Prefer jagged arrays over multidimensional" + }, + "fullDescription": { + "text": "A jagged array is an array whose elements are arrays. The arrays that make up the elements can be of different sizes, leading to less wasted space for some sets of data." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1814", + "properties": { + "category": "Performance", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1815", + "shortDescription": { + "text": "Override equals and operator equals on value types" + }, + "fullDescription": { + "text": "For value types, the inherited implementation of Equals uses the Reflection library and compares the contents of all fields. Reflection is computationally expensive, and comparing every field for equality might be unnecessary. If you expect users to compare or sort instances, or to use instances as hash table keys, your value type should implement Equals." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1815", + "properties": { + "category": "Performance", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1816", + "shortDescription": { + "text": "Dispose methods should call SuppressFinalize" + }, + "fullDescription": { + "text": "A method that is an implementation of Dispose does not call GC.SuppressFinalize; or a method that is not an implementation of Dispose calls GC.SuppressFinalize; or a method calls GC.SuppressFinalize and passes something other than this (Me in Visual Basic)." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1816", + "properties": { + "category": "Usage", + "executionTimeInSeconds": "0.020", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1819", + "shortDescription": { + "text": "Properties should not return arrays" + }, + "fullDescription": { + "text": "Arrays that are returned by properties are not write-protected, even when the property is read-only. To keep the array tamper-proof, the property must return a copy of the array. Typically, users will not understand the adverse performance implications of calling such a property." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1819", + "properties": { + "category": "Performance", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1820", + "shortDescription": { + "text": "Test for empty strings using string length" + }, + "fullDescription": { + "text": "Comparing strings by using the String.Length property or the String.IsNullOrEmpty method is significantly faster than using Equals." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1820", + "properties": { + "category": "Performance", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1821", + "shortDescription": { + "text": "Remove empty Finalizers" + }, + "fullDescription": { + "text": "Finalizers should be avoided where possible, to avoid the additional performance overhead involved in tracking object lifetime." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1821", + "properties": { + "category": "Performance", + "executionTimeInSeconds": "0.003", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1822", + "shortDescription": { + "text": "Mark members as static" + }, + "fullDescription": { + "text": "Members that do not access instance data or call instance methods can be marked as static. After you mark the methods as static, the compiler will emit nonvirtual call sites to these members. This can give you a measurable performance gain for performance-sensitive code." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1822", + "properties": { + "category": "Performance", + "executionTimeInSeconds": "0.071", + "executionTimeInPercentage": "1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1823", + "shortDescription": { + "text": "Avoid unused private fields" + }, + "fullDescription": { + "text": "Private fields were detected that do not appear to be accessed in the assembly." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1823", + "properties": { + "category": "Performance", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1824", + "shortDescription": { + "text": "Mark assemblies with NeutralResourcesLanguageAttribute" + }, + "fullDescription": { + "text": "The NeutralResourcesLanguage attribute informs the ResourceManager of the language that was used to display the resources of a neutral culture for an assembly. This improves lookup performance for the first resource that you load and can reduce your working set." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1824", + "properties": { + "category": "Performance", + "executionTimeInSeconds": "0.014", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1825", + "shortDescription": { + "text": "Avoid zero-length array allocations" + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1825", + "properties": { + "category": "Performance", + "executionTimeInSeconds": "0.006", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1826", + "shortDescription": { + "text": "Do not use Enumerable methods on indexable collections" + }, + "fullDescription": { + "text": "This collection is directly indexable. Going through LINQ here causes unnecessary allocations and CPU work." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1826", + "properties": { + "category": "Performance", + "executionTimeInSeconds": "0.002", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1827", + "shortDescription": { + "text": "Do not use Count() or LongCount() when Any() can be used" + }, + "fullDescription": { + "text": "For non-empty collections, Count() and LongCount() enumerate the entire sequence, while Any() stops at the first item or the first item that satisfies a condition." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1827", + "properties": { + "category": "Performance", + "executionTimeInSeconds": "0.026", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1828", + "shortDescription": { + "text": "Do not use CountAsync() or LongCountAsync() when AnyAsync() can be used" + }, + "fullDescription": { + "text": "For non-empty collections, CountAsync() and LongCountAsync() enumerate the entire sequence, while AnyAsync() stops at the first item or the first item that satisfies a condition." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1828", + "properties": { + "category": "Performance", + "executionTimeInSeconds": "0.026", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1829", + "shortDescription": { + "text": "Use Length/Count property instead of Count() when available" + }, + "fullDescription": { + "text": "Enumerable.Count() potentially enumerates the sequence while a Length/Count property is a direct access." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1829", + "properties": { + "category": "Performance", + "executionTimeInSeconds": "0.026", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1830", + "shortDescription": { + "text": "Prefer strongly-typed Append and Insert method overloads on StringBuilder" + }, + "fullDescription": { + "text": "StringBuilder.Append and StringBuilder.Insert provide overloads for multiple types beyond System.String. When possible, prefer the strongly-typed overloads over using ToString() and the string-based overload." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1830", + "properties": { + "category": "Performance", + "executionTimeInSeconds": "0.003", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1831", + "shortDescription": { + "text": "Use AsSpan or AsMemory instead of Range-based indexers when appropriate" + }, + "fullDescription": { + "text": "The Range-based indexer on string values produces a copy of requested portion of the string. This copy is usually unnecessary when it is implicitly used as a ReadOnlySpan or ReadOnlyMemory value. Use the AsSpan method to avoid the unnecessary copy." + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1831", + "properties": { + "category": "Performance", + "executionTimeInSeconds": "0.002", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1832", + "shortDescription": { + "text": "Use AsSpan or AsMemory instead of Range-based indexers when appropriate" + }, + "fullDescription": { + "text": "The Range-based indexer on array values produces a copy of requested portion of the array. This copy is usually unnecessary when it is implicitly used as a ReadOnlySpan or ReadOnlyMemory value. Use the AsSpan method to avoid the unnecessary copy." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1832", + "properties": { + "category": "Performance", + "executionTimeInSeconds": "0.002", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1833", + "shortDescription": { + "text": "Use AsSpan or AsMemory instead of Range-based indexers when appropriate" + }, + "fullDescription": { + "text": "The Range-based indexer on array values produces a copy of requested portion of the array. This copy is often unwanted when it is implicitly used as a Span or Memory value. Use the AsSpan method to avoid the copy." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1833", + "properties": { + "category": "Performance", + "executionTimeInSeconds": "0.002", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1834", + "shortDescription": { + "text": "Consider using 'StringBuilder.Append(char)' when applicable" + }, + "fullDescription": { + "text": "'StringBuilder.Append(char)' is more efficient than 'StringBuilder.Append(string)' when the string is a single character. When calling 'Append' with a constant, prefer using a constant char rather than a constant string containing one character." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1834", + "properties": { + "category": "Performance", + "executionTimeInSeconds": "0.002", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1835", + "shortDescription": { + "text": "Prefer the 'Memory'-based overloads for 'ReadAsync' and 'WriteAsync'" + }, + "fullDescription": { + "text": "'Stream' has a 'ReadAsync' overload that takes a 'Memory' as the first argument, and a 'WriteAsync' overload that takes a 'ReadOnlyMemory' as the first argument. Prefer calling the memory based overloads, which are more efficient." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1835", + "properties": { + "category": "Performance", + "executionTimeInSeconds": "0.006", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1836", + "shortDescription": { + "text": "Prefer IsEmpty over Count" + }, + "fullDescription": { + "text": "For determining whether the object contains or not any items, prefer using 'IsEmpty' property rather than retrieving the number of items from the 'Count' property and comparing it to 0 or 1." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1836", + "properties": { + "category": "Performance", + "executionTimeInSeconds": "0.026", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1837", + "shortDescription": { + "text": "Use 'Environment.ProcessId'" + }, + "fullDescription": { + "text": "'Environment.ProcessId' is simpler and faster than 'Process.GetCurrentProcess().Id'." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1837", + "properties": { + "category": "Performance", + "executionTimeInSeconds": "0.003", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1838", + "shortDescription": { + "text": "Avoid 'StringBuilder' parameters for P/Invokes" + }, + "fullDescription": { + "text": "Marshalling of 'StringBuilder' always creates a native buffer copy, resulting in multiple allocations for one marshalling operation." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1838", + "properties": { + "category": "Performance", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1839", + "shortDescription": { + "text": "Use 'Environment.ProcessPath'" + }, + "fullDescription": { + "text": "'Environment.ProcessPath' is simpler and faster than 'Process.GetCurrentProcess().MainModule.FileName'." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1839", + "properties": { + "category": "Performance", + "executionTimeInSeconds": "0.003", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1840", + "shortDescription": { + "text": "Use 'Environment.CurrentManagedThreadId'" + }, + "fullDescription": { + "text": "'Environment.CurrentManagedThreadId' is simpler and faster than 'Thread.CurrentThread.ManagedThreadId'." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1840", + "properties": { + "category": "Performance", + "executionTimeInSeconds": "0.003", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1841", + "shortDescription": { + "text": "Prefer Dictionary.Contains methods" + }, + "fullDescription": { + "text": "'ContainsKey' is usually O(1), while 'Keys.Contains' may be O(n) in some cases. Additionally, many dictionary implementations lazily initialize the Keys collection to cut back on allocations." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1841", + "properties": { + "category": "Performance", + "executionTimeInSeconds": "0.006", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1842", + "shortDescription": { + "text": "Do not use 'WhenAll' with a single task" + }, + "fullDescription": { + "text": "Using 'WhenAll' with a single task may result in performance loss, await or return the task instead." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1842", + "properties": { + "category": "Performance", + "executionTimeInSeconds": "0.004", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1843", + "shortDescription": { + "text": "Do not use 'WaitAll' with a single task" + }, + "fullDescription": { + "text": "Using 'WaitAll' with a single task may result in performance loss, await or return the task instead." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1843", + "properties": { + "category": "Performance", + "executionTimeInSeconds": "0.004", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1844", + "shortDescription": { + "text": "Provide memory-based overrides of async methods when subclassing 'Stream'" + }, + "fullDescription": { + "text": "To improve performance, override the memory-based async methods when subclassing 'Stream'. Then implement the array-based methods in terms of the memory-based methods." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1844", + "properties": { + "category": "Performance", + "executionTimeInSeconds": "0.008", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1845", + "shortDescription": { + "text": "Use span-based 'string.Concat'" + }, + "fullDescription": { + "text": "It is more efficient to use 'AsSpan' and 'string.Concat', instead of 'Substring' and a concatenation operator." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1845", + "properties": { + "category": "Performance", + "executionTimeInSeconds": "0.011", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1846", + "shortDescription": { + "text": "Prefer 'AsSpan' over 'Substring'" + }, + "fullDescription": { + "text": "'AsSpan' is more efficient than 'Substring'. 'Substring' performs an O(n) string copy, while 'AsSpan' does not and has a constant cost." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1846", + "properties": { + "category": "Performance", + "executionTimeInSeconds": "0.016", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1847", + "shortDescription": { + "text": "Use char literal for a single character lookup" + }, + "fullDescription": { + "text": "'string.Contains(char)' is available as a better performing overload for single char lookup." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1847", + "properties": { + "category": "Performance", + "executionTimeInSeconds": "0.004", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1848", + "shortDescription": { + "text": "Use the LoggerMessage delegates" + }, + "fullDescription": { + "text": "For improved performance, use the LoggerMessage delegates." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1848", + "properties": { + "category": "Performance", + "executionTimeInSeconds": "0.004", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1849", + "shortDescription": { + "text": "Call async methods when in an async method" + }, + "fullDescription": { + "text": "When inside a Task-returning method, use the async version of methods, if they exist." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1849", + "properties": { + "category": "Performance", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1850", + "shortDescription": { + "text": "Prefer static 'HashData' method over 'ComputeHash'" + }, + "fullDescription": { + "text": "It is more efficient to use the static 'HashData' method over creating and managing a HashAlgorithm instance to call 'ComputeHash'." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1850", + "properties": { + "category": "Performance", + "executionTimeInSeconds": "0.138", + "executionTimeInPercentage": "2", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1851", + "shortDescription": { + "text": "Possible multiple enumerations of 'IEnumerable' collection" + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1851", + "properties": { + "category": "Performance", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Dataflow", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1852", + "shortDescription": { + "text": "Seal internal types" + }, + "fullDescription": { + "text": "When a type is not accessible outside its assembly and has no subtypes within its containing assembly, it can be safely sealed. Sealing types can improve performance." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1852", + "properties": { + "category": "Performance", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode", + "CompilationEnd" + ] + } + }, + { + "id": "CA1853", + "shortDescription": { + "text": "Unnecessary call to 'Dictionary.ContainsKey(key)'" + }, + "fullDescription": { + "text": "Do not guard 'Dictionary.Remove(key)' with 'Dictionary.ContainsKey(key)'. The former already checks whether the key exists, and will not throw if it does not." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1853", + "properties": { + "category": "Performance", + "executionTimeInSeconds": "0.011", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1854", + "shortDescription": { + "text": "Prefer the 'IDictionary.TryGetValue(TKey, out TValue)' method" + }, + "fullDescription": { + "text": "Prefer a 'TryGetValue' call over a Dictionary indexer access guarded by a 'ContainsKey' check. 'ContainsKey' and the indexer both would lookup the key under the hood, so using 'TryGetValue' removes the extra lookup." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1854", + "properties": { + "category": "Performance", + "executionTimeInSeconds": "0.023", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1855", + "shortDescription": { + "text": "Prefer 'Clear' over 'Fill'" + }, + "fullDescription": { + "text": "It is more efficient to use 'Clear', instead of 'Fill' with default value." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1855", + "properties": { + "category": "Performance", + "executionTimeInSeconds": "0.014", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1856", + "shortDescription": { + "text": "Incorrect usage of ConstantExpected attribute" + }, + "fullDescription": { + "text": "ConstantExpected attribute is not applied correctly on the parameter." + }, + "defaultConfiguration": { + "level": "error" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1856", + "properties": { + "category": "Performance", + "executionTimeInSeconds": "0.019", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1857", + "shortDescription": { + "text": "A constant is expected for the parameter" + }, + "fullDescription": { + "text": "The parameter expects a constant for optimal performance." + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1857", + "properties": { + "category": "Performance", + "executionTimeInSeconds": "0.019", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1858", + "shortDescription": { + "text": "Use 'StartsWith' instead of 'IndexOf'" + }, + "fullDescription": { + "text": "It is both clearer and faster to use 'StartsWith' instead of comparing the result of 'IndexOf' to zero." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1858", + "properties": { + "category": "Performance", + "executionTimeInSeconds": "0.006", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1859", + "shortDescription": { + "text": "Use concrete types when possible for improved performance" + }, + "fullDescription": { + "text": "Using concrete types avoids virtual or interface call overhead and enables inlining." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1859", + "properties": { + "category": "Performance", + "executionTimeInSeconds": "0.069", + "executionTimeInPercentage": "1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1860", + "shortDescription": { + "text": "Avoid using 'Enumerable.Any()' extension method" + }, + "fullDescription": { + "text": "Prefer using 'IsEmpty', 'Count' or 'Length' properties whichever available, rather than calling 'Enumerable.Any()'. The intent is clearer and it is more performant than using 'Enumerable.Any()' extension method." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1860", + "properties": { + "category": "Performance", + "executionTimeInSeconds": "0.004", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1861", + "shortDescription": { + "text": "Avoid constant arrays as arguments" + }, + "fullDescription": { + "text": "Constant arrays passed as arguments are not reused when called repeatedly, which implies a new array is created each time. Consider extracting them to 'static readonly' fields to improve performance if the passed array is not mutated within the called method." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1861", + "properties": { + "category": "Performance", + "executionTimeInSeconds": "0.008", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1862", + "shortDescription": { + "text": "Use the 'StringComparison' method overloads to perform case-insensitive string comparisons" + }, + "fullDescription": { + "text": "Avoid calling 'ToLower', 'ToUpper', 'ToLowerInvariant' and 'ToUpperInvariant' to perform case-insensitive string comparisons because they lead to an allocation. Instead, prefer calling the method overloads of 'Contains', 'IndexOf' and 'StartsWith' that take a 'StringComparison' enum value to perform case-insensitive comparisons. Switching to using an overload that takes a 'StringComparison' might cause subtle changes in behavior, so it's important to conduct thorough testing after applying the suggestion. Additionally, if a culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase'." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1862", + "properties": { + "category": "Performance", + "executionTimeInSeconds": "0.005", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1863", + "shortDescription": { + "text": "Use 'CompositeFormat'" + }, + "fullDescription": { + "text": "Cache and use a 'CompositeFormat' instance as the argument to this formatting operation, rather than passing in the original format string. This reduces the cost of the formatting operation." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1863", + "properties": { + "category": "Performance", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1864", + "shortDescription": { + "text": "Prefer the 'IDictionary.TryAdd(TKey, TValue)' method" + }, + "fullDescription": { + "text": "Prefer a 'TryAdd' call over an 'Add' call guarded by a 'ContainsKey' check. 'TryAdd' behaves the same as 'Add', except that when the specified key already exists, it returns 'false' instead of throwing an exception." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1864", + "properties": { + "category": "Performance", + "executionTimeInSeconds": "0.023", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1865", + "shortDescription": { + "text": "Use char overload" + }, + "fullDescription": { + "text": "The char overload is a better performing overload than a string with a single char." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1865", + "properties": { + "category": "Performance", + "executionTimeInSeconds": "0.422", + "executionTimeInPercentage": "7", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1866", + "shortDescription": { + "text": "Use char overload" + }, + "fullDescription": { + "text": "The char overload is a better performing overload than a string with a single char." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1866", + "properties": { + "category": "Performance", + "executionTimeInSeconds": "0.422", + "executionTimeInPercentage": "7", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1867", + "shortDescription": { + "text": "Use char overload" + }, + "fullDescription": { + "text": "The char overload is a better performing overload than a string with a single char." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1867", + "properties": { + "category": "Performance", + "executionTimeInSeconds": "0.422", + "executionTimeInPercentage": "7", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1868", + "shortDescription": { + "text": "Unnecessary call to 'Contains(item)'" + }, + "fullDescription": { + "text": "Do not guard 'Add(item)' or 'Remove(item)' with 'Contains(item)' for the set. The former two already check whether the item exists and will return if it was added or removed." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1868", + "properties": { + "category": "Performance", + "executionTimeInSeconds": "0.011", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1869", + "shortDescription": { + "text": "Cache and reuse 'JsonSerializerOptions' instances" + }, + "fullDescription": { + "text": "Avoid creating a new 'JsonSerializerOptions' instance for every serialization operation. Cache and reuse instances instead. Single use 'JsonSerializerOptions' instances can substantially degrade the performance of your application." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1869", + "properties": { + "category": "Performance", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1870", + "shortDescription": { + "text": "Use a cached 'SearchValues' instance" + }, + "fullDescription": { + "text": "Using a cached 'SearchValues' instance is more efficient than passing values to 'IndexOfAny'/'ContainsAny' directly." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1870", + "properties": { + "category": "Performance", + "executionTimeInSeconds": "0.026", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1871", + "shortDescription": { + "text": "Do not pass a nullable struct to 'ArgumentNullException.ThrowIfNull'" + }, + "fullDescription": { + "text": "'ArgumentNullException.ThrowIfNull' accepts an 'object', so passing a nullable struct may cause the value to be boxed." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1871", + "properties": { + "category": "Performance", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA1872", + "shortDescription": { + "text": "Prefer 'Convert.ToHexString' and 'Convert.ToHexStringLower' over call chains based on 'BitConverter.ToString'" + }, + "fullDescription": { + "text": "Use 'Convert.ToHexString' or 'Convert.ToHexStringLower' when encoding bytes to a hexadecimal string representation. These methods are more efficient and allocation-friendly than using 'BitConverter.ToString' in combination with 'String.Replace' to replace dashes and 'String.ToLower'." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1872", + "properties": { + "category": "Performance", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2000", + "shortDescription": { + "text": "Dispose objects before losing scope" + }, + "fullDescription": { + "text": "If a disposable object is not explicitly disposed before all references to it are out of scope, the object will be disposed at some indeterminate time when the garbage collector runs the finalizer of the object. Because an exceptional event might occur that will prevent the finalizer of the object from running, the object should be explicitly disposed instead." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2000", + "properties": { + "category": "Reliability", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Dataflow", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2002", + "shortDescription": { + "text": "Do not lock on objects with weak identity" + }, + "fullDescription": { + "text": "An object is said to have a weak identity when it can be directly accessed across application domain boundaries. A thread that tries to acquire a lock on an object that has a weak identity can be blocked by a second thread in a different application domain that has a lock on the same object." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2002", + "properties": { + "category": "Reliability", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2007", + "shortDescription": { + "text": "Consider calling ConfigureAwait on the awaited task" + }, + "fullDescription": { + "text": "When an asynchronous method awaits a Task directly, continuation occurs in the same thread that created the task. Consider calling Task.ConfigureAwait(Boolean) to signal your intention for continuation. Call ConfigureAwait(false) on the task to schedule continuations to the thread pool, thereby avoiding a deadlock on the UI thread. Passing false is a good option for app-independent libraries. Calling ConfigureAwait(true) on the task has the same behavior as not explicitly calling ConfigureAwait. By explicitly calling this method, you're letting readers know you intentionally want to perform the continuation on the original synchronization context." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2007", + "properties": { + "category": "Reliability", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2008", + "shortDescription": { + "text": "Do not create tasks without passing a TaskScheduler" + }, + "fullDescription": { + "text": "Do not create tasks unless you are using one of the overloads that takes a TaskScheduler. The default is to schedule on TaskScheduler.Current, which would lead to deadlocks. Either use TaskScheduler.Default to schedule on the thread pool, or explicitly pass TaskScheduler.Current to make your intentions clear." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2008", + "properties": { + "category": "Reliability", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2009", + "shortDescription": { + "text": "Do not call ToImmutableCollection on an ImmutableCollection value" + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2009", + "properties": { + "category": "Reliability", + "executionTimeInSeconds": "0.003", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2011", + "shortDescription": { + "text": "Avoid infinite recursion" + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2011", + "properties": { + "category": "Reliability", + "executionTimeInSeconds": "0.002", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2012", + "shortDescription": { + "text": "Use ValueTasks correctly" + }, + "fullDescription": { + "text": "ValueTasks returned from member invocations are intended to be directly awaited. Attempts to consume a ValueTask multiple times or to directly access one's result before it's known to be completed may result in an exception or corruption. Ignoring such a ValueTask is likely an indication of a functional bug and may degrade performance." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2012", + "properties": { + "category": "Reliability", + "executionTimeInSeconds": "0.019", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2013", + "shortDescription": { + "text": "Do not use ReferenceEquals with value types" + }, + "fullDescription": { + "text": "Value type typed arguments are uniquely boxed for each call to this method, therefore the result can be unexpected." + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2013", + "properties": { + "category": "Reliability", + "executionTimeInSeconds": "0.003", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2014", + "shortDescription": { + "text": "Do not use stackalloc in loops" + }, + "fullDescription": { + "text": "Stack space allocated by a stackalloc is only released at the end of the current method's invocation. Using it in a loop can result in unbounded stack growth and eventual stack overflow conditions." + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2014", + "properties": { + "category": "Reliability", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2015", + "shortDescription": { + "text": "Do not define finalizers for types derived from MemoryManager" + }, + "fullDescription": { + "text": "Adding a finalizer to a type derived from MemoryManager may permit memory to be freed while it is still in use by a Span." + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2015", + "properties": { + "category": "Reliability", + "executionTimeInSeconds": "0.014", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2016", + "shortDescription": { + "text": "Forward the 'CancellationToken' parameter to methods" + }, + "fullDescription": { + "text": "Forward the 'CancellationToken' parameter to methods to ensure the operation cancellation notifications gets properly propagated, or pass in 'CancellationToken.None' explicitly to indicate intentionally not propagating the token." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2016", + "properties": { + "category": "Reliability", + "executionTimeInSeconds": "0.012", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2017", + "shortDescription": { + "text": "Parameter count mismatch" + }, + "fullDescription": { + "text": "Number of parameters supplied in the logging message template do not match the number of named placeholders." + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2017", + "properties": { + "category": "Reliability", + "executionTimeInSeconds": "0.004", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2018", + "shortDescription": { + "text": "'Buffer.BlockCopy' expects the number of bytes to be copied for the 'count' argument" + }, + "fullDescription": { + "text": "'Buffer.BlockCopy' expects the number of bytes to be copied for the 'count' argument. Using 'Array.Length' may not match the number of bytes that needs to be copied." + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2018", + "properties": { + "category": "Reliability", + "executionTimeInSeconds": "0.005", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2019", + "shortDescription": { + "text": "Improper 'ThreadStatic' field initialization" + }, + "fullDescription": { + "text": "'ThreadStatic' fields should be initialized lazily on use, not with inline initialization nor explicitly in a static constructor, which would only initialize the field on the thread that runs the type's static constructor." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2019", + "properties": { + "category": "Reliability", + "executionTimeInSeconds": "0.005", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2020", + "shortDescription": { + "text": "Prevent behavioral change" + }, + "fullDescription": { + "text": "Some built-in operators added in .NET 7 behave differently when overflowing than did the corresponding user-defined operators in .NET 6 and earlier versions. Some operators that previously threw in an unchecked context now don't throw unless wrapped within a checked context. Also, some operators that did not previously throw in a checked context now throw unless wrapped in an unchecked context." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2020", + "properties": { + "category": "Reliability", + "executionTimeInSeconds": "0.004", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2021", + "shortDescription": { + "text": "Do not call Enumerable.Cast or Enumerable.OfType with incompatible types" + }, + "fullDescription": { + "text": "Enumerable.Cast and Enumerable.OfType require compatible types to function expectedly. \u000d\u000aThe generic cast (IL 'unbox.any') used by the sequence returned by Enumerable.Cast will throw InvalidCastException at runtime on elements of the types specified. \u000d\u000aThe generic type check (C# 'is' operator/IL 'isinst') used by Enumerable.OfType will never succeed with elements of types specified, resulting in an empty sequence. \u000d\u000aWidening and user defined conversions are not supported with generic types." + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2021", + "properties": { + "category": "Reliability", + "executionTimeInSeconds": "0.018", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2022", + "shortDescription": { + "text": "Avoid inexact read with 'Stream.Read'" + }, + "fullDescription": { + "text": "A call to 'Stream.Read' may return fewer bytes than requested, resulting in unreliable code if the return value is not checked." + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2022", + "properties": { + "category": "Reliability", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2100", + "shortDescription": { + "text": "Review SQL queries for security vulnerabilities" + }, + "fullDescription": { + "text": "SQL queries that directly use user input can be vulnerable to SQL injection attacks. Review this SQL query for potential vulnerabilities, and consider using a parameterized SQL query." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2100", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Dataflow", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2101", + "shortDescription": { + "text": "Specify marshaling for P/Invoke string arguments" + }, + "fullDescription": { + "text": "A platform invoke member allows partially trusted callers, has a string parameter, and does not explicitly marshal the string. This can cause a potential security vulnerability." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2101", + "properties": { + "category": "Globalization", + "executionTimeInSeconds": "0.008", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2119", + "shortDescription": { + "text": "Seal methods that satisfy private interfaces" + }, + "fullDescription": { + "text": "An inheritable public type provides an overridable method implementation of an internal (Friend in Visual Basic) interface. To fix a violation of this rule, prevent the method from being overridden outside the assembly." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2119", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2153", + "shortDescription": { + "text": "Do Not Catch Corrupted State Exceptions" + }, + "fullDescription": { + "text": "Catching corrupted state exceptions could mask errors (such as access violations), resulting in inconsistent state of execution or making it easier for attackers to compromise system. Instead, catch and handle a more specific set of exception type(s) or re-throw the exception." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2153", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2200", + "shortDescription": { + "text": "Rethrow to preserve stack details" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2200", + "properties": { + "category": "Usage", + "executionTimeInSeconds": "0.002", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2201", + "shortDescription": { + "text": "Do not raise reserved exception types" + }, + "fullDescription": { + "text": "An exception of type that is not sufficiently specific or reserved by the runtime should never be raised by user code. This makes the original error difficult to detect and debug. If this exception instance might be thrown, use a different exception type." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2201", + "properties": { + "category": "Usage", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2207", + "shortDescription": { + "text": "Initialize value type static fields inline" + }, + "fullDescription": { + "text": "A value type declares an explicit static constructor. To fix a violation of this rule, initialize all static data when it is declared and remove the static constructor." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2207", + "properties": { + "category": "Usage", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2208", + "shortDescription": { + "text": "Instantiate argument exceptions correctly" + }, + "fullDescription": { + "text": "A call is made to the default (parameterless) constructor of an exception type that is or derives from ArgumentException, or an incorrect string argument is passed to a parameterized constructor of an exception type that is or derives from ArgumentException." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2208", + "properties": { + "category": "Usage", + "executionTimeInSeconds": "0.004", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2211", + "shortDescription": { + "text": "Non-constant fields should not be visible" + }, + "fullDescription": { + "text": "Static fields that are neither constants nor read-only are not thread-safe. Access to such a field must be carefully controlled and requires advanced programming techniques to synchronize access to the class object." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2211", + "properties": { + "category": "Usage", + "executionTimeInSeconds": "0.002", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2213", + "shortDescription": { + "text": "Disposable fields should be disposed" + }, + "fullDescription": { + "text": "A type that implements System.IDisposable declares fields that are of types that also implement IDisposable. The Dispose method of the field is not called by the Dispose method of the declaring type. To fix a violation of this rule, call Dispose on fields that are of types that implement IDisposable if you are responsible for allocating and releasing the unmanaged resources held by the field." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2213", + "properties": { + "category": "Usage", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Dataflow", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2214", + "shortDescription": { + "text": "Do not call overridable methods in constructors" + }, + "fullDescription": { + "text": "Virtual methods defined on the class should not be called from constructors. If a derived class has overridden the method, the derived class version will be called (before the derived class constructor is called)." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2214", + "properties": { + "category": "Usage", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2215", + "shortDescription": { + "text": "Dispose methods should call base class dispose" + }, + "fullDescription": { + "text": "A type that implements System.IDisposable inherits from a type that also implements IDisposable. The Dispose method of the inheriting type does not call the Dispose method of the parent type. To fix a violation of this rule, call base.Dispose in your Dispose method." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2215", + "properties": { + "category": "Usage", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2216", + "shortDescription": { + "text": "Disposable types should declare finalizer" + }, + "fullDescription": { + "text": "A type that implements System.IDisposable and has fields that suggest the use of unmanaged resources does not implement a finalizer, as described by Object.Finalize." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2216", + "properties": { + "category": "Usage", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2217", + "shortDescription": { + "text": "Do not mark enums with FlagsAttribute" + }, + "fullDescription": { + "text": "An externally visible enumeration is marked by using FlagsAttribute, and it has one or more values that are not powers of two or a combination of the other defined values on the enumeration." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2217", + "properties": { + "category": "Usage", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2219", + "shortDescription": { + "text": "Do not raise exceptions in finally clauses" + }, + "fullDescription": { + "text": "When an exception is raised in a finally clause, the new exception hides the active exception. This makes the original error difficult to detect and debug." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2219", + "properties": { + "category": "Usage", + "executionTimeInSeconds": "0.004", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2225", + "shortDescription": { + "text": "Operator overloads have named alternates" + }, + "fullDescription": { + "text": "An operator overload was detected, and the expected named alternative method was not found. The named alternative member provides access to the same functionality as the operator and is provided for developers who program in languages that do not support overloaded operators." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2225", + "properties": { + "category": "Usage", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2226", + "shortDescription": { + "text": "Operators should have symmetrical overloads" + }, + "fullDescription": { + "text": "A type implements the equality or inequality operator and does not implement the opposite operator." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2226", + "properties": { + "category": "Usage", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2227", + "shortDescription": { + "text": "Collection properties should be read only" + }, + "fullDescription": { + "text": "A writable collection property allows a user to replace the collection with a different collection. A read-only property stops the collection from being replaced but still allows the individual members to be set." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2227", + "properties": { + "category": "Usage", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2231", + "shortDescription": { + "text": "Overload operator equals on overriding value type Equals" + }, + "fullDescription": { + "text": "In most programming languages there is no default implementation of the equality operator (==) for value types. If your programming language supports operator overloads, you should consider implementing the equality operator. Its behavior should be identical to that of Equals." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2231", + "properties": { + "category": "Usage", + "executionTimeInSeconds": "0.014", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2234", + "shortDescription": { + "text": "Pass system uri objects instead of strings" + }, + "fullDescription": { + "text": "A call is made to a method that has a string parameter whose name contains \"uri\", \"URI\", \"urn\", \"URN\", \"url\", or \"URL\". The declaring type of the method contains a corresponding method overload that has a System.Uri parameter." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2234", + "properties": { + "category": "Usage", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2235", + "shortDescription": { + "text": "Mark all non-serializable fields" + }, + "fullDescription": { + "text": "An instance field of a type that is not serializable is declared in a type that is serializable." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2235", + "properties": { + "category": "Usage", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2237", + "shortDescription": { + "text": "Mark ISerializable types with serializable" + }, + "fullDescription": { + "text": "To be recognized by the common language runtime as serializable, types must be marked by using the SerializableAttribute attribute even when the type uses a custom serialization routine through implementation of the ISerializable interface." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2237", + "properties": { + "category": "Usage", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2241", + "shortDescription": { + "text": "Provide correct arguments to formatting methods" + }, + "fullDescription": { + "text": "The format argument that is passed to System.String.Format does not contain a format item that corresponds to each object argument, or vice versa." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2241", + "properties": { + "category": "Usage", + "executionTimeInSeconds": "0.093", + "executionTimeInPercentage": "1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2242", + "shortDescription": { + "text": "Test for NaN correctly" + }, + "fullDescription": { + "text": "This expression tests a value against Single.Nan or Double.Nan. Use Single.IsNan(Single) or Double.IsNan(Double) to test the value." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2242", + "properties": { + "category": "Usage", + "executionTimeInSeconds": "0.005", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2243", + "shortDescription": { + "text": "Attribute string literals should parse correctly" + }, + "fullDescription": { + "text": "The string literal parameter of an attribute does not parse correctly for a URL, a GUID, or a version." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2243", + "properties": { + "category": "Usage", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "PortedFromFxCop", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2244", + "shortDescription": { + "text": "Do not duplicate indexed element initializations" + }, + "fullDescription": { + "text": "Indexed elements in objects initializers must initialize unique elements. A duplicate index might overwrite a previous element initialization." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2244", + "properties": { + "category": "Usage", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2245", + "shortDescription": { + "text": "Do not assign a property to itself" + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2245", + "properties": { + "category": "Usage", + "executionTimeInSeconds": "0.002", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2246", + "shortDescription": { + "text": "Assigning symbol and its member in the same statement" + }, + "fullDescription": { + "text": "Assigning to a symbol and its member (field/property) in the same statement is not recommended. It is not clear if the member access was intended to use symbol's old value prior to the assignment or new value from the assignment in this statement. For clarity, consider splitting the assignments into separate statements." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2246", + "properties": { + "category": "Usage", + "executionTimeInSeconds": "0.003", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2247", + "shortDescription": { + "text": "Argument passed to TaskCompletionSource constructor should be TaskCreationOptions enum instead of TaskContinuationOptions enum" + }, + "fullDescription": { + "text": "TaskCompletionSource has constructors that take TaskCreationOptions that control the underlying Task, and constructors that take object state that's stored in the task. Accidentally passing a TaskContinuationOptions instead of a TaskCreationOptions will result in the call treating the options as state." + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2247", + "properties": { + "category": "Usage", + "executionTimeInSeconds": "0.003", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2248", + "shortDescription": { + "text": "Provide correct 'enum' argument to 'Enum.HasFlag'" + }, + "fullDescription": { + "text": "'Enum.HasFlag' method expects the 'enum' argument to be of the same 'enum' type as the instance on which the method is invoked and that this 'enum' is marked with 'System.FlagsAttribute'. If these are different 'enum' types, an unhandled exception will be thrown at runtime. If the 'enum' type is not marked with 'System.FlagsAttribute' the call will always return 'false' at runtime." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2248", + "properties": { + "category": "Usage", + "executionTimeInSeconds": "0.002", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2249", + "shortDescription": { + "text": "Consider using 'string.Contains' instead of 'string.IndexOf'" + }, + "fullDescription": { + "text": "Calls to 'string.IndexOf' where the result is used to check for the presence/absence of a substring can be replaced by 'string.Contains'." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2249", + "properties": { + "category": "Usage", + "executionTimeInSeconds": "0.075", + "executionTimeInPercentage": "1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2250", + "shortDescription": { + "text": "Use 'ThrowIfCancellationRequested'" + }, + "fullDescription": { + "text": "'ThrowIfCancellationRequested' automatically checks whether the token has been canceled, and throws an 'OperationCanceledException' if it has." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2250", + "properties": { + "category": "Usage", + "executionTimeInSeconds": "0.004", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2251", + "shortDescription": { + "text": "Use 'string.Equals'" + }, + "fullDescription": { + "text": "It is both clearer and likely faster to use 'string.Equals' instead of comparing the result of 'string.Compare' to zero." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2251", + "properties": { + "category": "Usage", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2252", + "shortDescription": { + "text": "This API requires opting into preview features" + }, + "fullDescription": { + "text": "An assembly has to opt into preview features before using them." + }, + "defaultConfiguration": { + "level": "error" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2252", + "properties": { + "category": "Usage", + "executionTimeInSeconds": "0.047", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2253", + "shortDescription": { + "text": "Named placeholders should not be numeric values" + }, + "fullDescription": { + "text": "Named placeholders in the logging message template should not be comprised of only numeric characters." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2253", + "properties": { + "category": "Usage", + "executionTimeInSeconds": "0.004", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2254", + "shortDescription": { + "text": "Template should be a static expression" + }, + "fullDescription": { + "text": "The logging message template should not vary between calls." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2254", + "properties": { + "category": "Usage", + "executionTimeInSeconds": "0.004", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2255", + "shortDescription": { + "text": "The 'ModuleInitializer' attribute should not be used in libraries" + }, + "fullDescription": { + "text": "Module initializers are intended to be used by application code to ensure an application's components are initialized before the application code begins executing. If library code declares a method with the 'ModuleInitializerAttribute', it can interfere with application initialization and also lead to limitations in that application's trimming abilities. Instead of using methods marked with 'ModuleInitializerAttribute', the library should expose methods that can be used to initialize any components within the library and allow the application to invoke the method during application initialization." + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2255", + "properties": { + "category": "Usage", + "executionTimeInSeconds": "0.002", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2256", + "shortDescription": { + "text": "All members declared in parent interfaces must have an implementation in a DynamicInterfaceCastableImplementation-attributed interface" + }, + "fullDescription": { + "text": "Types attributed with 'DynamicInterfaceCastableImplementationAttribute' act as an interface implementation for a type that implements the 'IDynamicInterfaceCastable' type. As a result, it must provide an implementation of all of the members defined in the inherited interfaces, because the type that implements 'IDynamicInterfaceCastable' will not provide them otherwise." + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2256", + "properties": { + "category": "Usage", + "executionTimeInSeconds": "0.028", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2257", + "shortDescription": { + "text": "Members defined on an interface with the 'DynamicInterfaceCastableImplementationAttribute' should be 'static'" + }, + "fullDescription": { + "text": "Since a type that implements 'IDynamicInterfaceCastable' may not implement a dynamic interface in metadata, calls to an instance interface member that is not an explicit implementation defined on this type are likely to fail at runtime. Mark new interface members 'static' to avoid runtime errors." + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2257", + "properties": { + "category": "Usage", + "executionTimeInSeconds": "0.028", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2258", + "shortDescription": { + "text": "Providing a 'DynamicInterfaceCastableImplementation' interface in Visual Basic is unsupported" + }, + "fullDescription": { + "text": "Providing a functional 'DynamicInterfaceCastableImplementationAttribute'-attributed interface requires the Default Interface Members feature, which is unsupported in Visual Basic." + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2258", + "properties": { + "category": "Usage", + "executionTimeInSeconds": "0.028", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2259", + "shortDescription": { + "text": "'ThreadStatic' only affects static fields" + }, + "fullDescription": { + "text": "'ThreadStatic' only affects static fields. When applied to instance fields, it has no impact on behavior." + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2259", + "properties": { + "category": "Usage", + "executionTimeInSeconds": "0.005", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2260", + "shortDescription": { + "text": "Use correct type parameter" + }, + "fullDescription": { + "text": "Generic math interfaces require the derived type itself to be used for the self recurring type parameter." + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2260", + "properties": { + "category": "Usage", + "executionTimeInSeconds": "0.008", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2261", + "shortDescription": { + "text": "Do not use ConfigureAwaitOptions.SuppressThrowing with Task" + }, + "fullDescription": { + "text": "The ConfigureAwaitOptions.SuppressThrowing option is only supported with the non-generic Task, not a Task. To use it with a Task, first cast to the base Task." + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2261", + "properties": { + "category": "Usage", + "executionTimeInSeconds": "0.011", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2262", + "shortDescription": { + "text": "Set 'MaxResponseHeadersLength' properly" + }, + "fullDescription": { + "text": "The property 'MaxResponseHeadersLength' is measured in kilobytes, not in bytes. The provided value is multiplied by 1024, which might be greater than your intended maximum length." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2262", + "properties": { + "category": "Usage", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2263", + "shortDescription": { + "text": "Prefer generic overload when type is known" + }, + "fullDescription": { + "text": "Using a generic overload is preferable to the 'System.Type' overload when the type is known, promoting cleaner and more type-safe code with improved compile-time checks." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2263", + "properties": { + "category": "Usage", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2264", + "shortDescription": { + "text": "Do not pass a non-nullable value to 'ArgumentNullException.ThrowIfNull'" + }, + "fullDescription": { + "text": "'ArgumentNullException.ThrowIfNull' throws when the passed argument is 'null'. Certain constructs like non-nullable structs, 'nameof()' and 'new' expressions are known to never be null, so 'ArgumentNullException.ThrowIfNull' will never throw." + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2264", + "properties": { + "category": "Usage", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2265", + "shortDescription": { + "text": "Do not compare Span to 'null' or 'default'" + }, + "fullDescription": { + "text": "Comparing a span to 'null' or 'default' might not do what you intended. 'default' and the 'null' literal are implicitly converted to 'Span.Empty'. Remove the redundant comparison or make the code more explicit by using 'IsEmpty'." + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2265", + "properties": { + "category": "Usage", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2300", + "shortDescription": { + "text": "Do not use insecure deserializer BinaryFormatter" + }, + "fullDescription": { + "text": "The method '{0}' is insecure when deserializing untrusted data. If you need to instead detect BinaryFormatter deserialization without a SerializationBinder set, then disable rule CA2300, and enable rules CA2301 and CA2302." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2300", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2301", + "shortDescription": { + "text": "Do not call BinaryFormatter.Deserialize without first setting BinaryFormatter.Binder" + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2301", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Dataflow", + "Telemetry", + "EnabledRuleInAggressiveMode", + "CompilationEnd" + ] + } + }, + { + "id": "CA2302", + "shortDescription": { + "text": "Ensure BinaryFormatter.Binder is set before calling BinaryFormatter.Deserialize" + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2302", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Dataflow", + "Telemetry", + "EnabledRuleInAggressiveMode", + "CompilationEnd" + ] + } + }, + { + "id": "CA2305", + "shortDescription": { + "text": "Do not use insecure deserializer LosFormatter" + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2305", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2310", + "shortDescription": { + "text": "Do not use insecure deserializer NetDataContractSerializer" + }, + "fullDescription": { + "text": "The method '{0}' is insecure when deserializing untrusted data. If you need to instead detect NetDataContractSerializer deserialization without a SerializationBinder set, then disable rule CA2310, and enable rules CA2311 and CA2312." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2310", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2311", + "shortDescription": { + "text": "Do not deserialize without first setting NetDataContractSerializer.Binder" + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2311", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Dataflow", + "Telemetry", + "EnabledRuleInAggressiveMode", + "CompilationEnd" + ] + } + }, + { + "id": "CA2312", + "shortDescription": { + "text": "Ensure NetDataContractSerializer.Binder is set before deserializing" + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2312", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Dataflow", + "Telemetry", + "EnabledRuleInAggressiveMode", + "CompilationEnd" + ] + } + }, + { + "id": "CA2315", + "shortDescription": { + "text": "Do not use insecure deserializer ObjectStateFormatter" + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2315", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2321", + "shortDescription": { + "text": "Do not deserialize with JavaScriptSerializer using a SimpleTypeResolver" + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2321", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Dataflow", + "Telemetry", + "EnabledRuleInAggressiveMode", + "CompilationEnd" + ] + } + }, + { + "id": "CA2322", + "shortDescription": { + "text": "Ensure JavaScriptSerializer is not initialized with SimpleTypeResolver before deserializing" + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2322", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Dataflow", + "Telemetry", + "EnabledRuleInAggressiveMode", + "CompilationEnd" + ] + } + }, + { + "id": "CA2326", + "shortDescription": { + "text": "Do not use TypeNameHandling values other than None" + }, + "fullDescription": { + "text": "Deserializing JSON when using a TypeNameHandling value other than None can be insecure. If you need to instead detect Json.NET deserialization when a SerializationBinder isn't specified, then disable rule CA2326, and enable rules CA2327, CA2328, CA2329, and CA2330." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2326", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2327", + "shortDescription": { + "text": "Do not use insecure JsonSerializerSettings" + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2327", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Dataflow", + "Telemetry", + "EnabledRuleInAggressiveMode", + "CompilationEnd" + ] + } + }, + { + "id": "CA2328", + "shortDescription": { + "text": "Ensure that JsonSerializerSettings are secure" + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2328", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Dataflow", + "Telemetry", + "EnabledRuleInAggressiveMode", + "CompilationEnd" + ] + } + }, + { + "id": "CA2329", + "shortDescription": { + "text": "Do not deserialize with JsonSerializer using an insecure configuration" + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2329", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Dataflow", + "Telemetry", + "EnabledRuleInAggressiveMode", + "CompilationEnd" + ] + } + }, + { + "id": "CA2330", + "shortDescription": { + "text": "Ensure that JsonSerializer has a secure configuration when deserializing" + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2330", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Dataflow", + "Telemetry", + "EnabledRuleInAggressiveMode", + "CompilationEnd" + ] + } + }, + { + "id": "CA2350", + "shortDescription": { + "text": "Do not use DataTable.ReadXml() with untrusted data" + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2350", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2351", + "shortDescription": { + "text": "Do not use DataSet.ReadXml() with untrusted data" + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2351", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2352", + "shortDescription": { + "text": "Unsafe DataSet or DataTable in serializable type can be vulnerable to remote code execution attacks" + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2352", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2353", + "shortDescription": { + "text": "Unsafe DataSet or DataTable in serializable type" + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2353", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2354", + "shortDescription": { + "text": "Unsafe DataSet or DataTable in deserialized object graph can be vulnerable to remote code execution attacks" + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2354", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2355", + "shortDescription": { + "text": "Unsafe DataSet or DataTable type found in deserializable object graph" + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2355", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2356", + "shortDescription": { + "text": "Unsafe DataSet or DataTable type in web deserializable object graph" + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2356", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2361", + "shortDescription": { + "text": "Ensure auto-generated class containing DataSet.ReadXml() is not used with untrusted data" + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2361", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA2362", + "shortDescription": { + "text": "Unsafe DataSet or DataTable in auto-generated serializable type can be vulnerable to remote code execution attacks" + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2362", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA3001", + "shortDescription": { + "text": "Review code for SQL injection vulnerabilities" + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca3001", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Dataflow", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA3002", + "shortDescription": { + "text": "Review code for XSS vulnerabilities" + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca3002", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Dataflow", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA3003", + "shortDescription": { + "text": "Review code for file path injection vulnerabilities" + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca3003", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Dataflow", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA3004", + "shortDescription": { + "text": "Review code for information disclosure vulnerabilities" + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca3004", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Dataflow", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA3005", + "shortDescription": { + "text": "Review code for LDAP injection vulnerabilities" + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca3005", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Dataflow", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA3006", + "shortDescription": { + "text": "Review code for process command injection vulnerabilities" + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca3006", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Dataflow", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA3007", + "shortDescription": { + "text": "Review code for open redirect vulnerabilities" + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca3007", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Dataflow", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA3008", + "shortDescription": { + "text": "Review code for XPath injection vulnerabilities" + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca3008", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Dataflow", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA3009", + "shortDescription": { + "text": "Review code for XML injection vulnerabilities" + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca3009", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Dataflow", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA3010", + "shortDescription": { + "text": "Review code for XAML injection vulnerabilities" + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca3010", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Dataflow", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA3011", + "shortDescription": { + "text": "Review code for DLL injection vulnerabilities" + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca3011", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Dataflow", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA3012", + "shortDescription": { + "text": "Review code for regex injection vulnerabilities" + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca3012", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Dataflow", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA3061", + "shortDescription": { + "text": "Do Not Add Schema By URL" + }, + "fullDescription": { + "text": "This overload of XmlSchemaCollection.Add method internally enables DTD processing on the XML reader instance used, and uses UrlResolver for resolving external XML entities. The outcome is information disclosure. Content from file system or network shares for the machine processing the XML can be exposed to attacker. In addition, an attacker can use this as a DoS vector." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca3061", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA3075", + "shortDescription": { + "text": "Insecure DTD processing in XML" + }, + "fullDescription": { + "text": "Using XmlTextReader.Load(), creating an insecure XmlReaderSettings instance when invoking XmlReader.Create(), setting the InnerXml property of the XmlDocument and enabling DTD processing using XmlUrlResolver insecurely can lead to information disclosure. Replace it with a call to the Load() method overload that takes an XmlReader instance, use XmlReader.Create() to accept XmlReaderSettings arguments or consider explicitly setting secure values. The DataViewSettingCollectionString property of DataViewManager should always be assigned from a trusted source, the DtdProcessing property should be set to false, and the XmlResolver property should be changed to XmlSecureResolver or null." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca3075", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA3076", + "shortDescription": { + "text": "Insecure XSLT script processing" + }, + "fullDescription": { + "text": "Providing an insecure XsltSettings instance and an insecure XmlResolver instance to XslCompiledTransform.Load method is potentially unsafe as it allows processing script within XSL, which on an untrusted XSL input may lead to malicious code execution. Either replace the insecure XsltSettings argument with XsltSettings.Default or an instance that has disabled document function and script execution, or replace the XmlResolver argument with null or an XmlSecureResolver instance. This message may be suppressed if the input is known to be from a trusted source and external resource resolution from locations that are not known in advance must be supported." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca3076", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA3077", + "shortDescription": { + "text": "Insecure Processing in API Design, XmlDocument and XmlTextReader" + }, + "fullDescription": { + "text": "Enabling DTD processing on all instances derived from XmlTextReader or  XmlDocument and using XmlUrlResolver for resolving external XML entities may lead to information disclosure. Ensure to set the XmlResolver property to null, create an instance of XmlSecureResolver when processing untrusted input, or use XmlReader.Create method with a secure XmlReaderSettings argument. Unless you need to enable it, ensure the DtdProcessing property is set to false." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca3077", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA3147", + "shortDescription": { + "text": "Mark Verb Handlers With Validate Antiforgery Token" + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca3147", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA5350", + "shortDescription": { + "text": "Do Not Use Weak Cryptographic Algorithms" + }, + "fullDescription": { + "text": "Cryptographic algorithms degrade over time as attacks become for advances to attacker get access to more computation. Depending on the type and application of this cryptographic algorithm, further degradation of the cryptographic strength of it may allow attackers to read enciphered messages, tamper with enciphered  messages, forge digital signatures, tamper with hashed content, or otherwise compromise any cryptosystem based on this algorithm. Replace encryption uses with the AES algorithm (AES-256, AES-192 and AES-128 are acceptable) with a key length greater than or equal to 128 bits. Replace hashing uses with a hashing function in the SHA-2 family, such as SHA-2 512, SHA-2 384, or SHA-2 256." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5350", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA5351", + "shortDescription": { + "text": "Do Not Use Broken Cryptographic Algorithms" + }, + "fullDescription": { + "text": "An attack making it computationally feasible to break this algorithm exists. This allows attackers to break the cryptographic guarantees it is designed to provide. Depending on the type and application of this cryptographic algorithm, this may allow attackers to read enciphered messages, tamper with enciphered  messages, forge digital signatures, tamper with hashed content, or otherwise compromise any cryptosystem based on this algorithm. Replace encryption uses with the AES algorithm (AES-256, AES-192 and AES-128 are acceptable) with a key length greater than or equal to 128 bits. Replace hashing uses with a hashing function in the SHA-2 family, such as SHA512, SHA384, or SHA256. Replace digital signature uses with RSA with a key length greater than or equal to 2048-bits, or ECDSA with a key length greater than or equal to 256 bits." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5351", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA5358", + "shortDescription": { + "text": "Review cipher mode usage with cryptography experts" + }, + "fullDescription": { + "text": "These cipher modes might be vulnerable to attacks. Consider using recommended modes (CBC, CTS)." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5358", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA5359", + "shortDescription": { + "text": "Do Not Disable Certificate Validation" + }, + "fullDescription": { + "text": "A certificate can help authenticate the identity of the server. Clients should validate the server certificate to ensure requests are sent to the intended server. If the ServerCertificateValidationCallback always returns 'true', any certificate will pass validation." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5359", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA5360", + "shortDescription": { + "text": "Do Not Call Dangerous Methods In Deserialization" + }, + "fullDescription": { + "text": "Insecure Deserialization is a vulnerability which occurs when untrusted data is used to abuse the logic of an application, inflict a Denial-of-Service (DoS) attack, or even execute arbitrary code upon it being deserialized. It’s frequently possible for malicious users to abuse these deserialization features when the application is deserializing untrusted data which is under their control. Specifically, invoke dangerous methods in the process of deserialization. Successful insecure deserialization attacks could allow an attacker to carry out attacks such as DoS attacks, authentication bypasses, and remote code execution." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5360", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode", + "CompilationEnd" + ] + } + }, + { + "id": "CA5361", + "shortDescription": { + "text": "Do Not Disable SChannel Use of Strong Crypto" + }, + "fullDescription": { + "text": "Starting with the .NET Framework 4.6, the System.Net.ServicePointManager and System.Net.Security.SslStream classes are recommended to use new protocols. The old ones have protocol weaknesses and are not supported. Setting Switch.System.Net.DontEnableSchUseStrongCrypto with true will use the old weak crypto check and opt out of the protocol migration." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5361", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Dataflow", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA5362", + "shortDescription": { + "text": "Potential reference cycle in deserialized object graph" + }, + "fullDescription": { + "text": "Review code that processes untrusted deserialized data for handling of unexpected reference cycles. An unexpected reference cycle should not cause the code to enter an infinite loop. Otherwise, an unexpected reference cycle can allow an attacker to DOS or exhaust the memory of the process when deserializing untrusted data." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5362", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode", + "CompilationEnd" + ] + } + }, + { + "id": "CA5363", + "shortDescription": { + "text": "Do Not Disable Request Validation" + }, + "fullDescription": { + "text": "Request validation is a feature in ASP.NET that examines HTTP requests and determines whether they contain potentially dangerous content. This check adds protection from markup or code in the URL query string, cookies, or posted form values that might have been added for malicious purposes. So, it is generally desirable and should be left enabled for defense in depth." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5363", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA5364", + "shortDescription": { + "text": "Do Not Use Deprecated Security Protocols" + }, + "fullDescription": { + "text": "Using a deprecated security protocol rather than the system default is risky." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5364", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA5365", + "shortDescription": { + "text": "Do Not Disable HTTP Header Checking" + }, + "fullDescription": { + "text": "HTTP header checking enables encoding of the carriage return and newline characters, \\r and \\n, that are found in response headers. This encoding can help to avoid injection attacks that exploit an application that echoes untrusted data contained by the header." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5365", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA5366", + "shortDescription": { + "text": "Use XmlReader for 'DataSet.ReadXml()'" + }, + "fullDescription": { + "text": "Processing XML from untrusted data may load dangerous external references, which should be restricted by using an XmlReader with a secure resolver or with DTD processing disabled." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5366", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA5367", + "shortDescription": { + "text": "Do Not Serialize Types With Pointer Fields" + }, + "fullDescription": { + "text": "Pointers are not \"type safe\" in the sense that you cannot guarantee the correctness of the memory they point at. So, serializing types with pointer fields is dangerous, as it may allow an attacker to control the pointer." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5367", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode", + "CompilationEnd" + ] + } + }, + { + "id": "CA5368", + "shortDescription": { + "text": "Set ViewStateUserKey For Classes Derived From Page" + }, + "fullDescription": { + "text": "Setting the ViewStateUserKey property can help you prevent attacks on your application by allowing you to assign an identifier to the view-state variable for individual users so that they cannot use the variable to generate an attack. Otherwise, there will be cross-site request forgery vulnerabilities." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5368", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA5369", + "shortDescription": { + "text": "Use XmlReader for 'XmlSerializer.Deserialize()'" + }, + "fullDescription": { + "text": "Processing XML from untrusted data may load dangerous external references, which should be restricted by using an XmlReader with a secure resolver or with DTD processing disabled." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5369", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA5370", + "shortDescription": { + "text": "Use XmlReader for XmlValidatingReader constructor" + }, + "fullDescription": { + "text": "Processing XML from untrusted data may load dangerous external references, which should be restricted by using an XmlReader with a secure resolver or with DTD processing disabled." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5370", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA5371", + "shortDescription": { + "text": "Use XmlReader for 'XmlSchema.Read()'" + }, + "fullDescription": { + "text": "Processing XML from untrusted data may load dangerous external references, which should be restricted by using an XmlReader with a secure resolver or with DTD processing disabled." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5371", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA5372", + "shortDescription": { + "text": "Use XmlReader for XPathDocument constructor" + }, + "fullDescription": { + "text": "Processing XML from untrusted data may load dangerous external references, which should be restricted by using an XmlReader with a secure resolver or with DTD processing disabled." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5372", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA5373", + "shortDescription": { + "text": "Do not use obsolete key derivation function" + }, + "fullDescription": { + "text": "Password-based key derivation should use PBKDF2 with SHA-2. Avoid using PasswordDeriveBytes since it generates a PBKDF1 key. Avoid using Rfc2898DeriveBytes.CryptDeriveKey since it doesn't use the iteration count or salt." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5373", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA5374", + "shortDescription": { + "text": "Do Not Use XslTransform" + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5374", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA5375", + "shortDescription": { + "text": "Do Not Use Account Shared Access Signature" + }, + "fullDescription": { + "text": "Shared Access Signatures(SAS) are a vital part of the security model for any application using Azure Storage, they should provide limited and safe permissions to your storage account to clients that don't have the account key. All of the operations available via a service SAS are also available via an account SAS, that is, account SAS is too powerful. So it is recommended to use Service SAS to delegate access more carefully." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5375", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA5376", + "shortDescription": { + "text": "Use SharedAccessProtocol HttpsOnly" + }, + "fullDescription": { + "text": "HTTPS encrypts network traffic. Use HttpsOnly, rather than HttpOrHttps, to ensure network traffic is always encrypted to help prevent disclosure of sensitive data." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5376", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Dataflow", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA5377", + "shortDescription": { + "text": "Use Container Level Access Policy" + }, + "fullDescription": { + "text": "No access policy identifier is specified, making tokens non-revocable." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5377", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Dataflow", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA5378", + "shortDescription": { + "text": "Do not disable ServicePointManagerSecurityProtocols" + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5378", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Dataflow", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA5379", + "shortDescription": { + "text": "Ensure Key Derivation Function algorithm is sufficiently strong" + }, + "fullDescription": { + "text": "Some implementations of the Rfc2898DeriveBytes class allow for a hash algorithm to be specified in a constructor parameter or overwritten in the HashAlgorithm property. If a hash algorithm is specified, then it should be SHA-256 or higher." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5379", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA5380", + "shortDescription": { + "text": "Do Not Add Certificates To Root Store" + }, + "fullDescription": { + "text": "By default, the Trusted Root Certification Authorities certificate store is configured with a set of public CAs that has met the requirements of the Microsoft Root Certificate Program. Since all trusted root CAs can issue certificates for any domain, an attacker can pick a weak or coercible CA that you install by yourself to target for an attack - and a single vulnerable, malicious or coercible CA undermines the security of the entire system. To make matters worse, these attacks can go unnoticed quite easily." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5380", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Dataflow", + "Telemetry", + "EnabledRuleInAggressiveMode", + "CompilationEnd" + ] + } + }, + { + "id": "CA5381", + "shortDescription": { + "text": "Ensure Certificates Are Not Added To Root Store" + }, + "fullDescription": { + "text": "By default, the Trusted Root Certification Authorities certificate store is configured with a set of public CAs that has met the requirements of the Microsoft Root Certificate Program. Since all trusted root CAs can issue certificates for any domain, an attacker can pick a weak or coercible CA that you install by yourself to target for an attack - and a single vulnerable, malicious or coercible CA undermines the security of the entire system. To make matters worse, these attacks can go unnoticed quite easily." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5381", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Dataflow", + "Telemetry", + "EnabledRuleInAggressiveMode", + "CompilationEnd" + ] + } + }, + { + "id": "CA5382", + "shortDescription": { + "text": "Use Secure Cookies In ASP.NET Core" + }, + "fullDescription": { + "text": "Applications available over HTTPS must use secure cookies." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5382", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Dataflow", + "Telemetry", + "EnabledRuleInAggressiveMode", + "CompilationEnd" + ] + } + }, + { + "id": "CA5383", + "shortDescription": { + "text": "Ensure Use Secure Cookies In ASP.NET Core" + }, + "fullDescription": { + "text": "Applications available over HTTPS must use secure cookies." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5383", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Dataflow", + "Telemetry", + "EnabledRuleInAggressiveMode", + "CompilationEnd" + ] + } + }, + { + "id": "CA5384", + "shortDescription": { + "text": "Do Not Use Digital Signature Algorithm (DSA)" + }, + "fullDescription": { + "text": "DSA is too weak to use." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5384", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA5385", + "shortDescription": { + "text": "Use Rivest-Shamir-Adleman (RSA) Algorithm With Sufficient Key Size" + }, + "fullDescription": { + "text": "Encryption algorithms are vulnerable to brute force attacks when too small a key size is used." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5385", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA5386", + "shortDescription": { + "text": "Avoid hardcoding SecurityProtocolType value" + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5386", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA5387", + "shortDescription": { + "text": "Do Not Use Weak Key Derivation Function With Insufficient Iteration Count" + }, + "fullDescription": { + "text": "When deriving cryptographic keys from user-provided inputs such as password, use sufficient iteration count (at least 100k)." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5387", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Dataflow", + "Telemetry", + "EnabledRuleInAggressiveMode", + "CompilationEnd" + ] + } + }, + { + "id": "CA5388", + "shortDescription": { + "text": "Ensure Sufficient Iteration Count When Using Weak Key Derivation Function" + }, + "fullDescription": { + "text": "When deriving cryptographic keys from user-provided inputs such as password, use sufficient iteration count (at least 100k)." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5388", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Dataflow", + "Telemetry", + "EnabledRuleInAggressiveMode", + "CompilationEnd" + ] + } + }, + { + "id": "CA5389", + "shortDescription": { + "text": "Do Not Add Archive Item's Path To The Target File System Path" + }, + "fullDescription": { + "text": "When extracting files from an archive and using the archive item's path, check if the path is safe. Archive path can be relative and can lead to file system access outside of the expected file system target path, leading to malicious config changes and remote code execution via lay-and-wait technique." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5389", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Dataflow", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA5390", + "shortDescription": { + "text": "Do not hard-code encryption key" + }, + "fullDescription": { + "text": "SymmetricAlgorithm's .Key property, or a method's rgbKey parameter, should never be a hard-coded value." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5390", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Dataflow", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA5391", + "shortDescription": { + "text": "Use antiforgery tokens in ASP.NET Core MVC controllers" + }, + "fullDescription": { + "text": "Handling a POST, PUT, PATCH, or DELETE request without validating an antiforgery token may be vulnerable to cross-site request forgery attacks. A cross-site request forgery attack can send malicious requests from an authenticated user to your ASP.NET Core MVC controller." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5391", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode", + "CompilationEnd" + ] + } + }, + { + "id": "CA5392", + "shortDescription": { + "text": "Use DefaultDllImportSearchPaths attribute for P/Invokes" + }, + "fullDescription": { + "text": "By default, P/Invokes using DllImportAttribute probe a number of directories, including the current working directory for the library to load. This can be a security issue for certain applications, leading to DLL hijacking." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5392", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA5393", + "shortDescription": { + "text": "Do not use unsafe DllImportSearchPath value" + }, + "fullDescription": { + "text": "There could be a malicious DLL in the default DLL search directories. Or, depending on where your application is run from, there could be a malicious DLL in the application's directory. Use a DllImportSearchPath value that specifies an explicit search path instead. The DllImportSearchPath flags that this rule looks for can be configured in .editorconfig." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5393", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA5394", + "shortDescription": { + "text": "Do not use insecure randomness" + }, + "fullDescription": { + "text": "Using a cryptographically weak pseudo-random number generator may allow an attacker to predict what security-sensitive value will be generated. Use a cryptographically strong random number generator if an unpredictable value is required, or ensure that weak pseudo-random numbers aren't used in a security-sensitive manner." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5394", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA5395", + "shortDescription": { + "text": "Miss HttpVerb attribute for action methods" + }, + "fullDescription": { + "text": "All the methods that create, edit, delete, or otherwise modify data do so in the [HttpPost] overload of the method, which needs to be protected with the anti forgery attribute from request forgery. Performing a GET operation should be a safe operation that has no side effects and doesn't modify your persisted data." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5395", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode", + "CompilationEnd" + ] + } + }, + { + "id": "CA5396", + "shortDescription": { + "text": "Set HttpOnly to true for HttpCookie" + }, + "fullDescription": { + "text": "As a defense in depth measure, ensure security sensitive HTTP cookies are marked as HttpOnly. This indicates web browsers should disallow scripts from accessing the cookies. Injected malicious scripts are a common way of stealing cookies." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5396", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Dataflow", + "Telemetry", + "EnabledRuleInAggressiveMode", + "CompilationEnd" + ] + } + }, + { + "id": "CA5397", + "shortDescription": { + "text": "Do not use deprecated SslProtocols values" + }, + "fullDescription": { + "text": "Older protocol versions of Transport Layer Security (TLS) are less secure than TLS 1.2 and TLS 1.3, and are more likely to have new vulnerabilities. Avoid older protocol versions to minimize risk." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5397", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA5398", + "shortDescription": { + "text": "Avoid hardcoded SslProtocols values" + }, + "fullDescription": { + "text": "Current Transport Layer Security protocol versions may become deprecated if vulnerabilities are found. Avoid hardcoding SslProtocols values to keep your application secure. Use 'None' to let the Operating System choose a version." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5398", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA5399", + "shortDescription": { + "text": "HttpClients should enable certificate revocation list checks" + }, + "fullDescription": { + "text": "Using HttpClient without providing a platform specific handler (WinHttpHandler or CurlHandler or HttpClientHandler) where the CheckCertificateRevocationList property is set to true, will allow revoked certificates to be accepted by the HttpClient as valid." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5399", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Dataflow", + "Telemetry", + "EnabledRuleInAggressiveMode", + "CompilationEnd" + ] + } + }, + { + "id": "CA5400", + "shortDescription": { + "text": "Ensure HttpClient certificate revocation list check is not disabled" + }, + "fullDescription": { + "text": "Using HttpClient without providing a platform specific handler (WinHttpHandler or CurlHandler or HttpClientHandler) where the CheckCertificateRevocationList property is set to true, will allow revoked certificates to be accepted by the HttpClient as valid." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5400", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Dataflow", + "Telemetry", + "EnabledRuleInAggressiveMode", + "CompilationEnd" + ] + } + }, + { + "id": "CA5401", + "shortDescription": { + "text": "Do not use CreateEncryptor with non-default IV" + }, + "fullDescription": { + "text": "Symmetric encryption should always use a non-repeatable initialization vector to prevent dictionary attacks." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5401", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Dataflow", + "Telemetry", + "EnabledRuleInAggressiveMode", + "CompilationEnd" + ] + } + }, + { + "id": "CA5402", + "shortDescription": { + "text": "Use CreateEncryptor with the default IV" + }, + "fullDescription": { + "text": "Symmetric encryption should always use a non-repeatable initialization vector to prevent dictionary attacks." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5402", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Dataflow", + "Telemetry", + "EnabledRuleInAggressiveMode", + "CompilationEnd" + ] + } + }, + { + "id": "CA5403", + "shortDescription": { + "text": "Do not hard-code certificate" + }, + "fullDescription": { + "text": "Hard-coded certificates in source code are vulnerable to being exploited." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5403", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Dataflow", + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA5404", + "shortDescription": { + "text": "Do not disable token validation checks" + }, + "fullDescription": { + "text": "Token validation checks ensure that while validating tokens, all aspects are analyzed and verified. Turning off validation can lead to security holes by allowing untrusted tokens to make it through validation." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5404", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "CA5405", + "shortDescription": { + "text": "Do not always skip token validation in delegates" + }, + "fullDescription": { + "text": "By setting critical TokenValidationParameter validation delegates to true, important authentication safeguards are disabled which can lead to tokens from any issuer or expired tokens being wrongly validated." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5405", + "properties": { + "category": "Security", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, + { + "id": "EF1001", + "shortDescription": { + "text": "Internal EF Core API usage." + }, + "properties": { + "category": "Usage", + "executionTimeInSeconds": "0.059", + "executionTimeInPercentage": "<1" + } + }, + { + "id": "EF1002", + "shortDescription": { + "text": "Risk of vulnerability to SQL injection." + }, + "properties": { + "category": "Security", + "executionTimeInSeconds": "0.005", + "executionTimeInPercentage": "<1" + } + }, + { + "id": "S100", + "shortDescription": { + "text": "Methods and properties should be named in PascalCase" + }, + "fullDescription": { + "text": "Shared naming conventions allow teams to collaborate efficiently." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-100", + "properties": { + "category": "Minor Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "0.062", + "executionTimeInPercentage": "1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S1006", + "shortDescription": { + "text": "Method overrides should not change parameter defaults" + }, + "fullDescription": { + "text": "Default arguments are determined by the static type of the object." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-1006", + "properties": { + "category": "Critical Code Smell", + "executionTimeInSeconds": "0.010", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S101", + "shortDescription": { + "text": "Types should be named in PascalCase" + }, + "fullDescription": { + "text": "Shared naming conventions allow teams to collaborate efficiently." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-101", + "properties": { + "category": "Minor Code Smell", + "executionTimeInSeconds": "0.062", + "executionTimeInPercentage": "1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S103", + "shortDescription": { + "text": "Lines should not be too long" + }, + "fullDescription": { + "text": "Scrolling horizontally to see a full line of code lowers the code readability." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-103", + "properties": { + "category": "Major Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S104", + "shortDescription": { + "text": "Files should not have too many lines of code" + }, + "fullDescription": { + "text": "When a source file grows too much, it can accumulate numerous responsibilities and become challenging to understand and maintain." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-104", + "properties": { + "category": "Major Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S1048", + "shortDescription": { + "text": "Finalizers should not throw exceptions" + }, + "fullDescription": { + "text": "The finalizers are used to perform any necessary final clean-up when the garbage collector is collecting a class instance. The programmer has no control over when the finalizer is called; the garbage collector decides when to call it." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-1048", + "properties": { + "category": "Blocker Bug", + "executionTimeInSeconds": "0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S105", + "shortDescription": { + "text": "Tabulation characters should not be used" + }, + "fullDescription": { + "text": "The tab width can differ from one development environment to another. Using tabs may require other developers to configure their environment (text editor, preferences, etc.) to read source code." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-105", + "properties": { + "category": "Minor Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S106", + "shortDescription": { + "text": "Standard outputs should not be used directly to log anything" + }, + "fullDescription": { + "text": "In software development, logs serve as a record of events within an application, providing crucial insights for debugging. When logging, it is essential to ensure that the logs are:" + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-106", + "properties": { + "category": "Major Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope" + ] + } + }, + { + "id": "S1066", + "shortDescription": { + "text": "Mergeable \"if\" statements should be combined" + }, + "fullDescription": { + "text": "Nested code - blocks of code inside blocks of code - is eventually necessary, but increases complexity. This is why keeping the code as flat as possible, by avoiding unnecessary nesting, is considered a good practice." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-1066", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "0.003", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S1067", + "shortDescription": { + "text": "Expressions should not be too complex" + }, + "fullDescription": { + "text": "The complexity of an expression is defined by the number of &&, || and condition ? ifTrue : ifFalse operators it contains." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-1067", + "properties": { + "category": "Critical Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S107", + "shortDescription": { + "text": "Methods should not have too many parameters" + }, + "fullDescription": { + "text": "Methods with a long parameter list are difficult to use because maintainers must figure out the role of each parameter and keep track of their position." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-107", + "properties": { + "category": "Major Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S1075", + "shortDescription": { + "text": "URIs should not be hardcoded" + }, + "fullDescription": { + "text": "Hard-coding a URI makes it difficult to test a program for a variety of reasons:" + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-1075", + "properties": { + "category": "Minor Code Smell", + "executionTimeInSeconds": "0.014", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S108", + "shortDescription": { + "text": "Nested blocks of code should not be left empty" + }, + "fullDescription": { + "text": "An empty code block is confusing. It will require some effort from maintainers to determine if it is intentional or indicates the implementation is incomplete." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-108", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "0.002", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S109", + "shortDescription": { + "text": "Magic numbers should not be used" + }, + "fullDescription": { + "text": "A magic number is a hard-coded numerical value that may lack context or meaning. They should not be used because they can make the code less readable and maintainable." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-109", + "properties": { + "category": "Major Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope" + ] + } + }, + { + "id": "S110", + "shortDescription": { + "text": "Inheritance tree of classes should not be too deep" + }, + "fullDescription": { + "text": "Inheritance is one of the most valuable concepts in object-oriented programming. It’s a way to categorize and reuse code by creating collections of attributes and behaviors called classes, which can be based on previously created classes." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-110", + "properties": { + "category": "Major Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S1104", + "shortDescription": { + "text": "Fields should not have public accessibility" + }, + "fullDescription": { + "text": "Public fields in public classes do not respect the encapsulation principle and have three main disadvantages:" + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-1104", + "properties": { + "category": "Minor Code Smell", + "executionTimeInSeconds": "0.002", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S1109", + "shortDescription": { + "text": "A close curly brace should be located at the beginning of a line" + }, + "fullDescription": { + "text": "Shared coding conventions make it possible for a team to efficiently collaborate. This rule makes it mandatory to place a close curly brace at the beginning of a line." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-1109", + "properties": { + "category": "Minor Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S1110", + "shortDescription": { + "text": "Redundant pairs of parentheses should be removed" + }, + "fullDescription": { + "text": "Parentheses can disambiguate the order of operations in complex expressions and make the code easier to understand." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-1110", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "0.002", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S1116", + "shortDescription": { + "text": "Empty statements should be removed" + }, + "fullDescription": { + "text": "Empty statements represented by a semicolon ; are statements that do not perform any operation. They are often the result of a typo or a misunderstanding of the language syntax. It is a good practice to remove empty statements since they don’t add value and lead to confusion and errors." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-1116", + "properties": { + "category": "Minor Code Smell", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S1117", + "shortDescription": { + "text": "Local variables should not shadow class fields or properties" + }, + "fullDescription": { + "text": "Shadowing occurs when a local variable has the same name as a variable, field, or property in an outer scope." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-1117", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "0.035", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S1118", + "shortDescription": { + "text": "Utility classes should not have public constructors" + }, + "fullDescription": { + "text": "Whenever there are portions of code that are duplicated and do not depend on the state of their container class, they can be centralized inside a \"utility class\". A utility class is a class that only has static members, hence it should not be instantiated." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-1118", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "0.009", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S112", + "shortDescription": { + "text": "General or reserved exceptions should never be thrown" + }, + "fullDescription": { + "text": "This rule raises an issue when a general or reserved exception is thrown." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-112", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "0.003", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S1121", + "shortDescription": { + "text": "Assignments should not be made from within sub-expressions" + }, + "fullDescription": { + "text": "A common code smell that can hinder the clarity of source code is making assignments within sub-expressions. This practice involves assigning a value to a variable inside a larger expression, such as within a loop or a conditional statement." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-1121", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "0.006", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S1123", + "shortDescription": { + "text": "\"Obsolete\" attributes should include explanations" + }, + "fullDescription": { + "text": "The Obsolete attribute can be applied with or without a message argument. Marking something Obsolete without including advice on why it’s obsolete or what to use instead will lead maintainers to waste time trying to figure those things out." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-1123", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S1125", + "shortDescription": { + "text": "Boolean literals should not be redundant" + }, + "fullDescription": { + "text": "A boolean literal can be represented in two different ways: true or false. They can be combined with logical operators (!, &&, ||, ==, !=) to produce logical expressions that represent truth values. However, comparing a boolean literal to a variable or expression that evaluates to a boolean value is unnecessary and can make the code harder to read and understand. The more complex a boolean expression is, the harder it will be for developers to understand its meaning and expected behavior, and it will favour the introduction of new bugs." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-1125", + "properties": { + "category": "Minor Code Smell", + "executionTimeInSeconds": "0.011", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S1128", + "shortDescription": { + "text": "Unnecessary \"using\" should be removed" + }, + "fullDescription": { + "text": "Unnecessary using directives refer to importing namespaces, types or creating aliases that are not used or referenced anywhere in the code." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-1128", + "properties": { + "category": "Minor Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S113", + "shortDescription": { + "text": "Files should end with a newline" + }, + "fullDescription": { + "text": "Some tools work better when files end with an empty line." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-113", + "properties": { + "category": "Minor Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S1133", + "shortDescription": { + "text": "Deprecated code should be removed" + }, + "fullDescription": { + "text": "This rule is meant to be used as a way to track code which is marked as being deprecated. Deprecated code should eventually be removed." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-1133", + "properties": { + "category": "Info Code Smell", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S1134", + "shortDescription": { + "text": "Track uses of \"FIXME\" tags" + }, + "fullDescription": { + "text": "FIXME tags are commonly used to mark places where a bug is suspected, but which the developer wants to deal with later." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-1134", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "0.022", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S1135", + "shortDescription": { + "text": "Track uses of \"TODO\" tags" + }, + "fullDescription": { + "text": "Developers often use TODO tags to mark areas in the code where additional work or improvements are needed but are not implemented immediately. However, these TODO tags sometimes get overlooked or forgotten, leading to incomplete or unfinished code. This rule aims to identify and address unattended TODO tags to ensure a clean and maintainable codebase. This description explores why this is a problem and how it can be fixed to improve the overall code quality." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-1135", + "properties": { + "category": "Info Code Smell", + "executionTimeInSeconds": "0.022", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S1144", + "shortDescription": { + "text": "Unused private types or members should be removed" + }, + "fullDescription": { + "text": "This rule raises an issue when a private/internal type or member is never referenced in the code." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-1144", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "0.190", + "executionTimeInPercentage": "3", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S1147", + "shortDescription": { + "text": "Exit methods should not be called" + }, + "fullDescription": { + "text": "Calling Environment.Exit(exitCode) or Application.Exit() terminates the process and returns an exit code to the operating system.." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-1147", + "properties": { + "category": "Blocker Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope" + ] + } + }, + { + "id": "S1151", + "shortDescription": { + "text": "\"switch case\" clauses should not have too many lines of code" + }, + "fullDescription": { + "text": "The switch statement should be used only to clearly define some new branches in the control flow. As soon as a case clause contains too many statements this highly decreases the readability of the overall control flow statement. In such case, the content of the case clause should be extracted into a dedicated method." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-1151", + "properties": { + "category": "Major Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope" + ] + } + }, + { + "id": "S1155", + "shortDescription": { + "text": "\"Any()\" should be used to test for emptiness" + }, + "fullDescription": { + "text": "When you call Any(), it clearly communicates the code’s intention, which is to check if the collection is empty. Using Count() == 0 for this purpose is less direct and makes the code slightly more complex. However, there are some cases where special attention should be paid:" + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-1155", + "properties": { + "category": "Minor Code Smell", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S1163", + "shortDescription": { + "text": "Exceptions should not be thrown in finally blocks" + }, + "fullDescription": { + "text": "If an exception is already being thrown within the try block or caught in a catch block, throwing another exception in the finally block will override the original exception. This means that the original exception’s message and stack trace will be lost, potentially making it challenging to diagnose and troubleshoot the root cause of the problem." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-1163", + "properties": { + "category": "Critical Code Smell", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S1168", + "shortDescription": { + "text": "Empty arrays and collections should be returned instead of null" + }, + "fullDescription": { + "text": "Returning null or default instead of an actual collection forces the method callers to explicitly test for null, making the code more complex and less readable." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-1168", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "0.011", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S1172", + "shortDescription": { + "text": "Unused method parameters should be removed" + }, + "fullDescription": { + "text": "A typical code smell known as unused function parameters refers to parameters declared in a function but not used anywhere within the function’s body. While this might seem harmless at first glance, it can lead to confusion and potential errors in your code. Disregarding the values passed to such parameters, the function’s behavior will be the same, but the programmer’s intention won’t be clearly expressed anymore. Therefore, removing function parameters that are not being utilized is considered best practice." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-1172", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "0.036", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S1185", + "shortDescription": { + "text": "Overriding members should do more than simply call the same member in the base class" + }, + "fullDescription": { + "text": "Overriding a method just to call the same method from the base class without performing any other actions is useless and misleading. The only time this is justified is in sealed overriding methods, where the effect is to lock in the parent class behavior. This rule ignores overrides of Equals and GetHashCode." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-1185", + "properties": { + "category": "Minor Code Smell", + "executionTimeInSeconds": "0.025", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S1186", + "shortDescription": { + "text": "Methods should not be empty" + }, + "fullDescription": { + "text": "An empty method is generally considered bad practice and can lead to confusion, readability, and maintenance issues. Empty methods bring no functionality and are misleading to others as they might think the method implementation fulfills a specific and identified requirement." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-1186", + "properties": { + "category": "Critical Code Smell", + "executionTimeInSeconds": "0.006", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S1192", + "shortDescription": { + "text": "String literals should not be duplicated" + }, + "fullDescription": { + "text": "Duplicated string literals make the process of refactoring complex and error-prone, as any change would need to be propagated on all occurrences." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-1192", + "properties": { + "category": "Minor Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S1199", + "shortDescription": { + "text": "Nested code blocks should not be used" + }, + "fullDescription": { + "text": "Nested code blocks create new scopes where variables declared within are inaccessible from the outside, and their lifespan ends with the block." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-1199", + "properties": { + "category": "Minor Code Smell", + "executionTimeInSeconds": "0.002", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S1200", + "shortDescription": { + "text": "Classes should not be coupled to too many other classes" + }, + "fullDescription": { + "text": "According to the Single Responsibility Principle, introduced by Robert C. Martin in his book \"Principles of Object Oriented Design\", a class should have only one responsibility:" + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-1200", + "properties": { + "category": "Major Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope" + ] + } + }, + { + "id": "S1206", + "shortDescription": { + "text": "\"Equals(Object)\" and \"GetHashCode()\" should be overridden in pairs" + }, + "fullDescription": { + "text": "Suppose you override Object.Equals in a type, you must also override Object.GetHashCode. If two objects are equal according to the Equals method, then calling GetHashCode on each of them must yield the same integer. If this is not the case, many collections, such as a Hashtable or a Dictionary won’t handle class instances correctly." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-1206", + "properties": { + "category": "Minor Bug", + "executionTimeInSeconds": "0.010", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S121", + "shortDescription": { + "text": "Control structures should use curly braces" + }, + "fullDescription": { + "text": "Control structures are code statements that impact the program’s control flow (e.g., if statements, for loops, etc.)" + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-121", + "properties": { + "category": "Critical Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S1210", + "shortDescription": { + "text": "\"Equals\" and the comparison operators should be overridden when implementing \"IComparable\"" + }, + "fullDescription": { + "text": "When you implement IComparable or IComparable on a class you should also override Equals(object) and overload the comparison operators (==, !=, <, <=, >, >=). That’s because the CLR cannot automatically call your CompareTo implementation from Equals(object) or from the base comparison operator implementations. Additionally, it is best practice to override GetHashCode along with Equals." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-1210", + "properties": { + "category": "Minor Code Smell", + "executionTimeInSeconds": "0.012", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S1215", + "shortDescription": { + "text": "\"GC.Collect\" should not be called" + }, + "fullDescription": { + "text": "GC.Collect is a method that forces or suggests to the garbage collector to run a collection of objects in the managed heap that are no longer being used and free their memory." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-1215", + "properties": { + "category": "Critical Code Smell", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S122", + "shortDescription": { + "text": "Statements should be on separate lines" + }, + "fullDescription": { + "text": "Putting multiple statements on a single line lowers the code readability and makes debugging the code more complex." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-122", + "properties": { + "category": "Major Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S1226", + "shortDescription": { + "text": "Method parameters, caught exceptions and foreach variables' initial values should not be ignored" + }, + "fullDescription": { + "text": "While it is technically correct to assign to parameters from within method bodies, doing so before the parameter value is read is likely a bug. Instead, initial values of parameters, caught exceptions, and foreach parameters should be, if not treated as final, then at least read before reassignment." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-1226", + "properties": { + "category": "Minor Bug", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S1227", + "shortDescription": { + "text": "break statements should not be used except for switch cases" + }, + "fullDescription": { + "text": "break; is an unstructured control flow statement which makes code harder to read." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-1227", + "properties": { + "category": "Minor Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S1244", + "shortDescription": { + "text": "Floating point numbers should not be tested for equality" + }, + "fullDescription": { + "text": "Floating point numbers in C# (and in most other programming languages) are not precise. They are a binary approximation of the actual value. This means that even if two floating point numbers appear to be equal, they might not be due to the tiny differences in their binary representation." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-1244", + "properties": { + "category": "Major Bug", + "executionTimeInSeconds": "0.002", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S125", + "shortDescription": { + "text": "Sections of code should not be commented out" + }, + "fullDescription": { + "text": "Commented-out code distracts the focus from the actual executed code. It creates a noise that increases maintenance code. And because it is never executed, it quickly becomes out of date and invalid." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-125", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "0.015", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S126", + "shortDescription": { + "text": "\"if ... else if\" constructs should end with \"else\" clauses" + }, + "fullDescription": { + "text": "This rule applies whenever an if statement is followed by one or more else if statements; the final else if should be followed by an else statement." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-126", + "properties": { + "category": "Critical Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S1264", + "shortDescription": { + "text": "A \"while\" loop should be used instead of a \"for\" loop" + }, + "fullDescription": { + "text": "Using a for loop without its typical structure (initialization, condition, increment) can be confusing. In those cases, it is better to use a while loop as it is more readable." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-1264", + "properties": { + "category": "Minor Code Smell", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S127", + "shortDescription": { + "text": "\"for\" loop stop conditions should be invariant" + }, + "fullDescription": { + "text": "A for loop stop condition should test the loop counter against an invariant value (i.e. one that is true at both the beginning and ending of every loop iteration). Ideally, this means that the stop condition is set to a local variable just before the loop begins." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-127", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S1301", + "shortDescription": { + "text": "\"switch\" statements should have at least 3 \"case\" clauses" + }, + "fullDescription": { + "text": "switch statements and expressions are useful when there are many different cases depending on the value of the same expression." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-1301", + "properties": { + "category": "Minor Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S1309", + "shortDescription": { + "text": "Track uses of in-source issue suppressions" + }, + "fullDescription": { + "text": "This rule allows you to track the usage of the SuppressMessage attributes and #pragma warning disable mechanism." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-1309", + "properties": { + "category": "Info Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S131", + "shortDescription": { + "text": "\"switch/Select\" statements should contain a \"default/Case Else\" clauses" + }, + "fullDescription": { + "text": "The requirement for a final default clause is defensive programming. The clause should either take appropriate action, or contain a suitable comment as to why no action is taken. Even when the switch covers all current values of an enum, a default case should still be used because there is no guarantee that the enum won’t be extended." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-131", + "properties": { + "category": "Critical Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S1312", + "shortDescription": { + "text": "Logger fields should be \"private static readonly\"" + }, + "fullDescription": { + "text": "Regardless of the logging framework in use (Microsoft.Extension.Logging, Serilog, Log4net, NLog, …​​), logger fields should be:" + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-1312", + "properties": { + "category": "Minor Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope" + ] + } + }, + { + "id": "S1313", + "shortDescription": { + "text": "Using hardcoded IP addresses is security-sensitive" + }, + "fullDescription": { + "text": "Hardcoding IP addresses is security-sensitive. It has led in the past to the following vulnerabilities:" + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-1313", + "properties": { + "category": "Major Security Hotspot", + "executionTimeInSeconds": "0.003", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S134", + "shortDescription": { + "text": "Control flow statements \"if\", \"switch\", \"for\", \"foreach\", \"while\", \"do\" and \"try\" should not be nested too deeply" + }, + "fullDescription": { + "text": "Nested control flow statements if, switch, for, foreach, while, do, and try are often key ingredients in creating what’s known as \"Spaghetti code\". This code smell can make your program difficult to understand and maintain." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-134", + "properties": { + "category": "Critical Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S138", + "shortDescription": { + "text": "Functions should not have too many lines of code" + }, + "fullDescription": { + "text": "A function that grows too large tends to aggregate too many responsibilities." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-138", + "properties": { + "category": "Major Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope" + ] + } + }, + { + "id": "S1449", + "shortDescription": { + "text": "Culture should be specified for \"string\" operations" + }, + "fullDescription": { + "text": "string.ToLower(), ToUpper, IndexOf, LastIndexOf, and Compare are all culture-dependent, as are some (floating point number and DateTime-related) calls to ToString. Fortunately, all have variants which accept an argument specifying the culture or formatter to use. Leave that argument off and the call will use the system default culture, possibly creating problems with international characters." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-1449", + "properties": { + "category": "Minor Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope" + ] + } + }, + { + "id": "S1450", + "shortDescription": { + "text": "Private fields only used as local variables in methods should become local variables" + }, + "fullDescription": { + "text": "When the value of a private field is always assigned to in a class' methods before being read, then it is not being used to store class information. Therefore, it should become a local variable in the relevant methods to prevent any misunderstanding." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-1450", + "properties": { + "category": "Minor Code Smell", + "executionTimeInSeconds": "0.038", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S1451", + "shortDescription": { + "text": "Track lack of copyright and license headers" + }, + "fullDescription": { + "text": "Each source file should start with a header stating file ownership and the license which must be used to distribute the application." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-1451", + "properties": { + "category": "Blocker Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S1479", + "shortDescription": { + "text": "\"switch\" statements with many \"case\" clauses should have only one statement" + }, + "fullDescription": { + "text": "When switch statements have large sets of multi-line case clauses, the code becomes hard to read and maintain." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-1479", + "properties": { + "category": "Major Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S1481", + "shortDescription": { + "text": "Unused local variables should be removed" + }, + "fullDescription": { + "text": "An unused local variable is a variable that has been declared but is not used anywhere in the block of code where it is defined. It is dead code, contributing to unnecessary complexity and leading to confusion when reading the code. Therefore, it should be removed from your code to maintain clarity and efficiency." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-1481", + "properties": { + "category": "Minor Code Smell", + "executionTimeInSeconds": "0.054", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S1541", + "shortDescription": { + "text": "Methods and properties should not be too complex" + }, + "fullDescription": { + "text": "The cyclomatic complexity of methods and properties should not exceed a defined threshold. Complex code can perform poorly and will in any case be difficult to understand and therefore to maintain." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-1541", + "properties": { + "category": "Critical Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope" + ] + } + }, + { + "id": "S1607", + "shortDescription": { + "text": "Tests should not be ignored" + }, + "fullDescription": { + "text": "When a test fails due, for example, to infrastructure issues, you might want to ignore it temporarily. But without some kind of notation about why the test is being ignored, it may never be reactivated. Such tests are difficult to address without comprehensive knowledge of the project, and end up polluting their projects." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-1607", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S1643", + "shortDescription": { + "text": "Strings should not be concatenated using '+' in a loop" + }, + "fullDescription": { + "text": "Concatenating multiple string literals or strings using the + operator creates a new string object for each concatenation. This can lead to a large number of intermediate string objects and can be inefficient. The StringBuilder class is more efficient than string concatenation, especially when the operator is repeated over and over as in loops." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-1643", + "properties": { + "category": "Minor Code Smell", + "executionTimeInSeconds": "0.002", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S1656", + "shortDescription": { + "text": "Variables should not be self-assigned" + }, + "fullDescription": { + "text": "Re-assigning a variable to itself is a defect as it has no actual effect and indicates meaning to do something else. It usually means that:" + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-1656", + "properties": { + "category": "Major Bug", + "executionTimeInSeconds": "0.017", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S1659", + "shortDescription": { + "text": "Multiple variables should not be declared on the same line" + }, + "fullDescription": { + "text": "Declaring multiple variable on one line is difficult to read." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-1659", + "properties": { + "category": "Minor Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S1694", + "shortDescription": { + "text": "An abstract class should have both abstract and concrete methods" + }, + "fullDescription": { + "text": "A class with only abstract methods and no inheritable behavior should be converted to an interface." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-1694", + "properties": { + "category": "Minor Code Smell", + "executionTimeInSeconds": "0.045", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S1696", + "shortDescription": { + "text": "NullReferenceException should not be caught" + }, + "fullDescription": { + "text": "Catching NullReferenceException is generally considered a bad practice because it can hide bugs in your code. Instead of catching this exception, you should aim to prevent it. This makes your code more robust and easier to understand. In addition, constantly catching and handling NullReferenceException can lead to performance issues. Exceptions are expensive in terms of system resources, so they should be used cautiously and only for exceptional conditions, not for regular control flow." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-1696", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S1698", + "shortDescription": { + "text": "\"==\" should not be used when \"Equals\" is overridden" + }, + "fullDescription": { + "text": "Using the equality == and inequality != operators to compare two objects generally works. The operators can be overloaded, and therefore the comparison can resolve to the appropriate method. However, when the operators are used on interface instances, then == resolves to reference equality, which may result in unexpected behavior if implementing classes override Equals. Similarly, when a class overrides Equals, but instances are compared with non-overloaded ==, there is a high chance that value comparison was meant instead of the reference one." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-1698", + "properties": { + "category": "Minor Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope" + ] + } + }, + { + "id": "S1699", + "shortDescription": { + "text": "Constructors should only call non-overridable methods" + }, + "fullDescription": { + "text": "Calling an overridable method from a constructor could result in failures or strange behaviors when instantiating a subclass which overrides the method." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-1699", + "properties": { + "category": "Critical Code Smell", + "executionTimeInSeconds": "0.004", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S1751", + "shortDescription": { + "text": "Loops with at most one iteration should be refactored" + }, + "fullDescription": { + "text": "A loop statement with at most one iteration is equivalent to an if statement; the following block is executed only once." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-1751", + "properties": { + "category": "Major Bug", + "executionTimeInSeconds": "0.015", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S1764", + "shortDescription": { + "text": "Identical expressions should not be used on both sides of operators" + }, + "fullDescription": { + "text": "Using the same value on both sides of certain operators is a code defect. In the case of logical operators, it is either a copy/paste error and, therefore, a bug, or it is simply duplicated code and should be simplified. For bitwise operators and most binary mathematical operators, having the same value on both sides of an operator yields predictable results and should be simplified as well to avoid further code defects." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-1764", + "properties": { + "category": "Major Bug", + "executionTimeInSeconds": "0.016", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S1821", + "shortDescription": { + "text": "\"switch\" statements should not be nested" + }, + "fullDescription": { + "text": "Nested switch structures are difficult to understand because you can easily confuse the cases of an inner switch as belonging to an outer statement. Therefore nested switch statements should be avoided." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-1821", + "properties": { + "category": "Critical Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S1848", + "shortDescription": { + "text": "Objects should not be created to be dropped immediately without being used" + }, + "fullDescription": { + "text": "Creating objects that are not used is a vulnerability that can lead to unexpected behavior." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-1848", + "properties": { + "category": "Major Bug", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S1854", + "shortDescription": { + "text": "Unused assignments should be removed" + }, + "fullDescription": { + "text": "Dead stores refer to assignments made to local variables that are subsequently never used or immediately overwritten. Such assignments are unnecessary and don’t contribute to the functionality or clarity of the code. They may even negatively impact performance. Removing them enhances code cleanliness and readability. Even if the unnecessary operations do not do any harm in terms of the program’s correctness, they are - at best - a waste of computing resources." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-1854", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "0.286", + "executionTimeInPercentage": "4", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S1858", + "shortDescription": { + "text": "\"ToString()\" calls should not be redundant" + }, + "fullDescription": { + "text": "Invoking a method designed to return a string representation of an object which is already a string is a waste of keystrokes. Similarly, explicitly invoking ToString() when the compiler would do it implicitly is also needless code-bloat." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-1858", + "properties": { + "category": "Minor Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S1862", + "shortDescription": { + "text": "Related \"if/else if\" statements should not have the same condition" + }, + "fullDescription": { + "text": "A chain of if/else if statements is evaluated from top to bottom. At most, only one branch will be executed: the first statement with a condition that evaluates to true. Therefore, duplicating a condition leads to unreachable code inside the duplicated condition block. Usually, this is due to a copy/paste error." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-1862", + "properties": { + "category": "Major Bug", + "executionTimeInSeconds": "0.006", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S1871", + "shortDescription": { + "text": "Two branches in a conditional structure should not have exactly the same implementation" + }, + "fullDescription": { + "text": "When the same code is duplicated in two or more separate branches of a conditional, it can make the code harder to understand, maintain, and can potentially introduce bugs if one instance of the code is changed but others are not." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-1871", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "0.010", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S1905", + "shortDescription": { + "text": "Redundant casts should not be used" + }, + "fullDescription": { + "text": "Casting expressions are utilized to convert one data type to another, such as transforming an integer into a string. This is especially crucial in strongly typed languages like C, C++, C#, Java, Python, and others." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-1905", + "properties": { + "category": "Minor Code Smell", + "executionTimeInSeconds": "0.036", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S1939", + "shortDescription": { + "text": "Inheritance list should not be redundant" + }, + "fullDescription": { + "text": "An inheritance list entry is redundant if:" + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-1939", + "properties": { + "category": "Minor Code Smell", + "executionTimeInSeconds": "0.020", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S1940", + "shortDescription": { + "text": "Boolean checks should not be inverted" + }, + "fullDescription": { + "text": "It is needlessly complex to invert the result of a boolean comparison. The opposite comparison should be made instead." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-1940", + "properties": { + "category": "Minor Code Smell", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S1944", + "shortDescription": { + "text": "Invalid casts should be avoided" + }, + "fullDescription": { + "text": "A cast is an explicit conversion, which is a way to tell the compiler the intent to convert from one type to another." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-1944", + "properties": { + "category": "Critical Code Smell", + "executionTimeInSeconds": "0.132", + "executionTimeInPercentage": "2", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S1994", + "shortDescription": { + "text": "\"for\" loop increment clauses should modify the loops' counters" + }, + "fullDescription": { + "text": "The for loop is designed to iterate over a range using a counter variable, with the counter being updated in the loop’s increment section. Misusing this structure can lead to issues such as infinite loops if the counter is not updated correctly. If this is intentional, use a while or do while loop instead of a for loop." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-1994", + "properties": { + "category": "Critical Code Smell", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S2068", + "shortDescription": { + "text": "Hard-coded credentials are security-sensitive" + }, + "fullDescription": { + "text": "Because it is easy to extract strings from an application source code or binary, credentials should not be hard-coded. This is particularly true for applications that are distributed or that are open-source." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2068", + "properties": { + "category": "Blocker Security Hotspot", + "executionTimeInSeconds": "0.017", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S2077", + "shortDescription": { + "text": "Formatting SQL queries is security-sensitive" + }, + "fullDescription": { + "text": "Formatted SQL queries can be difficult to maintain, debug and can increase the risk of SQL injection when concatenating untrusted values into the query. However, this rule doesn’t detect SQL injections (unlike rule {rule:csharpsquid:S3649}), the goal is only to highlight complex/formatted queries." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2077", + "properties": { + "category": "Major Security Hotspot", + "executionTimeInSeconds": "0.002", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S2092", + "shortDescription": { + "text": "Creating cookies without the \"secure\" flag is security-sensitive" + }, + "fullDescription": { + "text": "When a cookie is protected with the secure attribute set to true it will not be send by the browser over an unencrypted HTTP request and thus cannot be observed by an unauthorized person during a man-in-the-middle attack." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2092", + "properties": { + "category": "Minor Security Hotspot", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S2094", + "shortDescription": { + "text": "Classes should not be empty" + }, + "fullDescription": { + "text": "There is no good excuse for an empty class. If it’s being used simply as a common extension point, it should be replaced with an interface. If it was stubbed in as a placeholder for future development it should be fleshed-out. In any other case, it should be eliminated." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2094", + "properties": { + "category": "Minor Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S2114", + "shortDescription": { + "text": "Collections should not be passed as arguments to their own methods" + }, + "fullDescription": { + "text": "Passing a collection as an argument to the collection’s own method is a code defect. Doing so might either have unexpected side effects or always have the same result." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2114", + "properties": { + "category": "Major Bug", + "executionTimeInSeconds": "0.002", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S2115", + "shortDescription": { + "text": "A secure password should be used when connecting to a database" + }, + "fullDescription": { + "text": "When accessing a database, an empty password should be avoided as it introduces a weakness." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2115", + "properties": { + "category": "Blocker Vulnerability", + "executionTimeInSeconds": "0.023", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S2123", + "shortDescription": { + "text": "Values should not be uselessly incremented" + }, + "fullDescription": { + "text": "When using the postfix increment operator, it is important to know that the result of the expression x++ is the value before the operation x." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2123", + "properties": { + "category": "Major Bug", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S2139", + "shortDescription": { + "text": "Exceptions should be either logged or rethrown but not both" + }, + "fullDescription": { + "text": "When an exception is logged and rethrown, the upstream code may not be aware that the exception has already been logged. As a result, the same exception gets logged multiple times, making it difficult to identify the root cause of the issue. This can be particularly problematic in multi-threaded applications where messages from other threads can be interwoven with the repeated log entries." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2139", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "0.003", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S2148", + "shortDescription": { + "text": "Underscores should be used to make large numbers readable" + }, + "fullDescription": { + "text": "Beginning with C# 7, it is possible to add underscores ('_') to numeric literals to enhance readability. The addition of underscores in this manner has no semantic meaning, but makes it easier for maintainers to understand the code." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2148", + "properties": { + "category": "Minor Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S2156", + "shortDescription": { + "text": "\"sealed\" classes should not have \"protected\" members" + }, + "fullDescription": { + "text": "The difference between private and protected visibility is that child classes can see and use protected members, but they cannot see private ones. Since a sealed class cannot have children, marking its members protected is confusingly pointless." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2156", + "properties": { + "category": "Minor Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S2166", + "shortDescription": { + "text": "Classes named like \"Exception\" should extend \"Exception\" or a subclass" + }, + "fullDescription": { + "text": "Clear, communicative naming is important in code. It helps maintainers and API users understand the intentions for and uses of a unit of code. Using \"exception\" in the name of a class that does not extend Exception or one of its subclasses is a clear violation of the expectation that a class' name will indicate what it is and/or does." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2166", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "0.005", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S2178", + "shortDescription": { + "text": "Short-circuit logic should be used in boolean contexts" + }, + "fullDescription": { + "text": "Short-circuit evaluation is an evaluation strategy for Boolean operators, that doesn’t evaluates the second argument of the operator if it is not needed to determine the result of the operation." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2178", + "properties": { + "category": "Blocker Code Smell", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S2183", + "shortDescription": { + "text": "Integral numbers should not be shifted by zero or more than their number of bits-1" + }, + "fullDescription": { + "text": "The shifting operators are used to do an arithmetic shift to the bits of an integral numeric value, either to the left or the right." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2183", + "properties": { + "category": "Minor Bug", + "executionTimeInSeconds": "0.019", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S2184", + "shortDescription": { + "text": "Results of integer division should not be assigned to floating point variables" + }, + "fullDescription": { + "text": "When division is performed on ints, the result will always be an int. You can assign that result to a double, float or decimal with automatic type conversion, but having started as an int, the result will likely not be what you expect. If the result of int division is assigned to a floating-point variable, precision will have been lost before the assignment. Instead, at least one operand should be cast or promoted to the final type before the operation takes place." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2184", + "properties": { + "category": "Minor Bug", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S2187", + "shortDescription": { + "text": "Test classes should contain at least one test case" + }, + "fullDescription": { + "text": "To ensure proper testing, it is important to include test cases in a test class. If a test class does not have any test cases, it can give the wrong impression that the class being tested has been thoroughly tested, when in reality, it has not." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2187", + "properties": { + "category": "Blocker Code Smell", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S2190", + "shortDescription": { + "text": "Loops and recursions should not be infinite" + }, + "fullDescription": { + "text": "Having an infinite loop or recursion will lead to a program failure or a program never finishing the execution." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2190", + "properties": { + "category": "Blocker Bug", + "executionTimeInSeconds": "0.119", + "executionTimeInPercentage": "2", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S2197", + "shortDescription": { + "text": "Modulus results should not be checked for direct equality" + }, + "fullDescription": { + "text": "When the modulus of a negative number is calculated, the result will either be negative or zero. Thus, comparing the modulus of a variable for equality with a positive number (or a negative one) could result in unexpected results." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2197", + "properties": { + "category": "Critical Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S2198", + "shortDescription": { + "text": "Unnecessary mathematical comparisons should not be made" + }, + "fullDescription": { + "text": "Certain mathematical comparisons will always return the same value, and should not be performed." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2198", + "properties": { + "category": "Critical Code Smell", + "executionTimeInSeconds": "0.004", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S2201", + "shortDescription": { + "text": "Methods without side effects should not have their return values ignored" + }, + "fullDescription": { + "text": "When you do not use the return value of a method with no side effects, it indicates that something is wrong. Either this method is unnecessary, or the source code does not behave as expected and could lead to code defects. For example, there are methods, such as DateTime.AddYears, that don’t change the value of the input object, but instead, they return a new object whose value is the result of this operation, and as a result that you will have unexpected effects if you do not use the return value." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2201", + "properties": { + "category": "Major Bug", + "executionTimeInSeconds": "0.006", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S2219", + "shortDescription": { + "text": "Runtime type checking should be simplified" + }, + "fullDescription": { + "text": "To check the type of an object there are several options:" + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2219", + "properties": { + "category": "Minor Code Smell", + "executionTimeInSeconds": "0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S2221", + "shortDescription": { + "text": "\"Exception\" should not be caught" + }, + "fullDescription": { + "text": "Catching System.Exception seems like an efficient way to handle multiple possible exceptions. Unfortunately, it traps all exception types, including the ones that were not intended to be caught. To prevent any misunderstandings, exception filters should be used. Alternatively, each exception type should be in a separate catch block." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2221", + "properties": { + "category": "Minor Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope" + ] + } + }, + { + "id": "S2223", + "shortDescription": { + "text": "Non-constant static fields should not be visible" + }, + "fullDescription": { + "text": "Unlike instance fields, which can only be accessed by code having a hold on the instance, static fields can be accessed by any code having visibility of the field and its type." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2223", + "properties": { + "category": "Critical Code Smell", + "executionTimeInSeconds": "0.002", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S2225", + "shortDescription": { + "text": "\"ToString()\" method should not return null" + }, + "fullDescription": { + "text": "Calling ToString() on an object should always return a string. Thus, overriding the ToString method should never return null, as it breaks the method’s implicit contract, and as a result the consumer’s expectations." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2225", + "properties": { + "category": "Major Bug", + "executionTimeInSeconds": "0.013", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S2234", + "shortDescription": { + "text": "Arguments should be passed in the same order as the method parameters" + }, + "fullDescription": { + "text": "Calling a method with argument variables whose names match the method parameter names but in a different order can cause confusion. It could indicate a mistake in the arguments' order, leading to unexpected results." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2234", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "0.024", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S2245", + "shortDescription": { + "text": "Using pseudorandom number generators (PRNGs) is security-sensitive" + }, + "fullDescription": { + "text": "PRNGs are algorithms that produce sequences of numbers that only approximate true randomness. While they are suitable for applications like simulations or modeling, they are not appropriate for security-sensitive contexts because their outputs can be predictable if the internal state is known." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2245", + "properties": { + "category": "Critical Security Hotspot", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S2251", + "shortDescription": { + "text": "A \"for\" loop update clause should move the counter in the right direction" + }, + "fullDescription": { + "text": "A for loop with a counter that moves in the wrong direction, away from the stop condition, is not an infinite loop. Because of wraparound, the loop will eventually reach its stop condition, but in doing so, it will probably run more times than anticipated, potentially causing unexpected behavior." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2251", + "properties": { + "category": "Major Bug", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S2252", + "shortDescription": { + "text": "For-loop conditions should be true at least once" + }, + "fullDescription": { + "text": "A for loop is a fundamental programming construct used to execute a block of code repeatedly. However, if the loop’s condition is false before the first iteration, the loop will never execute." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2252", + "properties": { + "category": "Major Bug", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S2257", + "shortDescription": { + "text": "Using non-standard cryptographic algorithms is security-sensitive" + }, + "fullDescription": { + "text": "The use of a non-standard algorithm is dangerous because a determined attacker may be able to break the algorithm and compromise whatever data has been protected. Standard algorithms like AES, RSA, SHA, …​ should be used instead." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2257", + "properties": { + "category": "Critical Security Hotspot", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S2275", + "shortDescription": { + "text": "Composite format strings should not lead to unexpected behavior at runtime" + }, + "fullDescription": { + "text": "Composite format strings in C# are evaluated at runtime, which means they are not verified by the compiler. Introducing an ill-formed format item, or indexing mismatch can lead to unexpected behaviors or runtime errors. The purpose of this rule is to perform static validation on composite format strings used in various string formatting functions to ensure their correct usage. This rule validates the proper behavior of composite formats when invoking the following methods:" + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2275", + "properties": { + "category": "Blocker Bug", + "executionTimeInSeconds": "0.012", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S2290", + "shortDescription": { + "text": "Field-like events should not be virtual" + }, + "fullDescription": { + "text": "Field-like events are events that do not have explicit add and remove accessors." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2290", + "properties": { + "category": "Critical Code Smell", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S2291", + "shortDescription": { + "text": "Overflow checking should not be disabled for \"Enumerable.Sum\"" + }, + "fullDescription": { + "text": "Enumerable.Sum() always executes addition in a checked context, so an OverflowException will be thrown if the value exceeds MaxValue, even if an unchecked context was specified. Therefore, using this method inside an unchecked context will only make the code more confusing, since the behavior will still be checked." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2291", + "properties": { + "category": "Critical Code Smell", + "executionTimeInSeconds": "0.002", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S2292", + "shortDescription": { + "text": "Trivial properties should be auto-implemented" + }, + "fullDescription": { + "text": "Trivial properties, which include no logic but setting and getting a backing field should be converted to auto-implemented properties, yielding cleaner and more readable code." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2292", + "properties": { + "category": "Minor Code Smell", + "executionTimeInSeconds": "0.017", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S2302", + "shortDescription": { + "text": "\"nameof\" should be used" + }, + "fullDescription": { + "text": "Because parameter names could be changed during refactoring, they should not be spelled out literally in strings. Instead, use nameof(), and the string that’s output will always be correct." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2302", + "properties": { + "category": "Critical Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope" + ] + } + }, + { + "id": "S2306", + "shortDescription": { + "text": "\"async\" and \"await\" should not be used as identifiers" + }, + "fullDescription": { + "text": "Since C# 5.0, async and await are contextual keywords. Contextual keywords do have a particular meaning in some contexts, but are not reserved and therefore can be used as variable names." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2306", + "properties": { + "category": "Blocker Code Smell", + "executionTimeInSeconds": "0.060", + "executionTimeInPercentage": "1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S2325", + "shortDescription": { + "text": "Methods and properties that don't access instance data should be static" + }, + "fullDescription": { + "text": "Methods and properties that don’t access instance data should be marked as static for the following reasons:" + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2325", + "properties": { + "category": "Minor Code Smell", + "executionTimeInSeconds": "0.029", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S2326", + "shortDescription": { + "text": "Unused type parameters should be removed" + }, + "fullDescription": { + "text": "Type parameters that aren’t used are dead code, which can only distract and possibly confuse developers during maintenance. Therefore, unused type parameters should be removed." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2326", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "0.025", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S2327", + "shortDescription": { + "text": "\"try\" statements with identical \"catch\" and/or \"finally\" blocks should be merged" + }, + "fullDescription": { + "text": "When multiple, adjacent try statements have duplicate catch and/or finally blocks, they should be merged to consolidate the catch/finally logic for cleaner, more readable code. Note that this applies even when there is intervening code outside any try block." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2327", + "properties": { + "category": "Major Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope" + ] + } + }, + { + "id": "S2328", + "shortDescription": { + "text": "\"GetHashCode\" should not reference mutable fields" + }, + "fullDescription": { + "text": "GetHashCode is used to file an object in a Dictionary or Hashtable. If GetHashCode uses non-readonly fields and those fields change after the object is stored, the object immediately becomes mis-filed in the Hashtable. Any subsequent test to see if the object is in the Hashtable will return a false negative." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2328", + "properties": { + "category": "Minor Bug", + "executionTimeInSeconds": "0.024", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S2330", + "shortDescription": { + "text": "Array covariance should not be used" + }, + "fullDescription": { + "text": "Array covariance is the principle that if an implicit or explicit reference conversion exits from type A to B, then the same conversion exists from the array type A[] to B[]." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2330", + "properties": { + "category": "Critical Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S2333", + "shortDescription": { + "text": "Redundant modifiers should not be used" + }, + "fullDescription": { + "text": "Unnecessary keywords simply clutter the code and should be removed. Specifically:" + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2333", + "properties": { + "category": "Minor Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S2339", + "shortDescription": { + "text": "Public constant members should not be used" + }, + "fullDescription": { + "text": "Constant members are copied at compile time to the call sites, instead of being fetched at runtime." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2339", + "properties": { + "category": "Critical Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S2342", + "shortDescription": { + "text": "Enumeration types should comply with a naming convention" + }, + "fullDescription": { + "text": "Shared naming conventions allow teams to collaborate efficiently. This rule checks that all enum names match a provided regular expression." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2342", + "properties": { + "category": "Minor Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S2344", + "shortDescription": { + "text": "Enumeration type names should not have \"Flags\" or \"Enum\" suffixes" + }, + "fullDescription": { + "text": "The information that an enumeration type is actually an enumeration or a set of flags should not be duplicated in its name." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2344", + "properties": { + "category": "Minor Code Smell", + "executionTimeInSeconds": "0.002", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S2345", + "shortDescription": { + "text": "Flags enumerations should explicitly initialize all their members" + }, + "fullDescription": { + "text": "When you annotate an Enum with the Flags attribute, you must not rely on the values that are automatically set by the language to the Enum members, but you should define the enumeration constants in powers of two (1, 2, 4, 8, and so on). Automatic value initialization will set the first member to zero and increment the value by one for each subsequent member. As a result, you won’t be able to use the enum members with bitwise operators." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2345", + "properties": { + "category": "Minor Bug", + "executionTimeInSeconds": "0.002", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S2346", + "shortDescription": { + "text": "Flags enumerations zero-value members should be named \"None\"" + }, + "fullDescription": { + "text": "An enumeration can be decorated with the FlagsAttribute to indicate that it can be used as a bit field: a set of flags, that can be independently set and reset." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2346", + "properties": { + "category": "Critical Code Smell", + "executionTimeInSeconds": "0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S2357", + "shortDescription": { + "text": "Fields should be private" + }, + "fullDescription": { + "text": "Fields should not be part of an API, and therefore should always be private. Indeed, they cannot be added to an interface for instance, and validation cannot be added later on without breaking backward compatibility. Instead, developers should encapsulate their fields into properties. Explicit property getters and setters can be introduced for validation purposes or to smooth the transition to a newer system." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2357", + "properties": { + "category": "Major Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope" + ] + } + }, + { + "id": "S2360", + "shortDescription": { + "text": "Optional parameters should not be used" + }, + "fullDescription": { + "text": "The overloading mechanism should be used in place of optional parameters for several reasons:" + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2360", + "properties": { + "category": "Critical Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S2365", + "shortDescription": { + "text": "Properties should not make collection or array copies" + }, + "fullDescription": { + "text": "Most developers expect property access to be as efficient as field access. However, if a property returns a copy of an array or collection, it will be much slower than a simple field access, contrary to the caller’s likely expectations. Therefore, such properties should be refactored into methods so that callers are not surprised by the unexpectedly poor performance." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2365", + "properties": { + "category": "Critical Code Smell", + "executionTimeInSeconds": "0.016", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S2368", + "shortDescription": { + "text": "Public methods should not have multidimensional array parameters" + }, + "fullDescription": { + "text": "Using multidimensional and jagged arrays as method parameters in C# can be challenging for developers." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2368", + "properties": { + "category": "Blocker Code Smell", + "executionTimeInSeconds": "0.015", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S2372", + "shortDescription": { + "text": "Exceptions should not be thrown from property getters" + }, + "fullDescription": { + "text": "Property getters should be simple operations that are always safe to call. If exceptions need to be thrown, it is best to convert the property to a method." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2372", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "0.004", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S2376", + "shortDescription": { + "text": "Write-only properties should not be used" + }, + "fullDescription": { + "text": "Properties with only setters are confusing and counterintuitive. Instead, a property getter should be added if possible, or the property should be replaced with a setter method." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2376", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "0.004", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S2386", + "shortDescription": { + "text": "Mutable fields should not be \"public static\"" + }, + "fullDescription": { + "text": "public static mutable fields of classes which are accessed directly should be protected to the degree possible. This can be done by reducing the accessibility of the field or by changing the return type to an immutable type." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2386", + "properties": { + "category": "Minor Code Smell", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S2387", + "shortDescription": { + "text": "Child class fields should not shadow parent class fields" + }, + "fullDescription": { + "text": "This rule is deprecated, and will eventually be removed." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2387", + "properties": { + "category": "Blocker Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope" + ] + } + }, + { + "id": "S2436", + "shortDescription": { + "text": "Types and methods should not have too many generic parameters" + }, + "fullDescription": { + "text": "A method or class with too many type parameters has likely aggregated too many responsibilities and should be split." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2436", + "properties": { + "category": "Major Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S2437", + "shortDescription": { + "text": "Unnecessary bit operations should not be performed" + }, + "fullDescription": { + "text": "Certain bitwise operations are not needed and should not be performed because their results are predictable." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2437", + "properties": { + "category": "Blocker Code Smell", + "executionTimeInSeconds": "0.002", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay", + "Unnecessary" + ] + } + }, + { + "id": "S2445", + "shortDescription": { + "text": "Blocks should be synchronized on read-only fields" + }, + "fullDescription": { + "text": "Locking on a class field synchronizes not on the field itself, but on the object assigned to it. Thus, there are some good practices to follow to avoid problems related to thread synchronization." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2445", + "properties": { + "category": "Major Bug", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S2479", + "shortDescription": { + "text": "Whitespace and control characters in string literals should be explicit" + }, + "fullDescription": { + "text": "Non-encoded control characters and whitespace characters are often injected in the source code because of a bad manipulation. They are either invisible or difficult to recognize, which can result in bugs when the string is not what the developer expects. If you actually need to use a control character use their encoded version:" + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2479", + "properties": { + "category": "Critical Code Smell", + "executionTimeInSeconds": "0.010", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S2486", + "shortDescription": { + "text": "Generic exceptions should not be ignored" + }, + "fullDescription": { + "text": "When exceptions occur, it is usually a bad idea to simply ignore them. Instead, it is better to handle them properly, or at least to log them." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2486", + "properties": { + "category": "Minor Code Smell", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S2551", + "shortDescription": { + "text": "Shared resources should not be used for locking" + }, + "fullDescription": { + "text": "The instance passed to the lock statement should be a dedicated private field." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2551", + "properties": { + "category": "Critical Bug", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S2612", + "shortDescription": { + "text": "Setting loose file permissions is security-sensitive" + }, + "fullDescription": { + "text": "In Unix, \"others\" class refers to all users except the owner of the file and the members of the group assigned to this file." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2612", + "properties": { + "category": "Major Security Hotspot", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S2629", + "shortDescription": { + "text": "Logging templates should be constant" + }, + "fullDescription": { + "text": "Logging arguments should not require evaluation in order to avoid unnecessary performance overhead. When passing concatenated strings or string interpolations directly into a logging method, the evaluation of these expressions occurs every time the logging method is called, regardless of the log level. This can lead to inefficient code execution and increased resource consumption." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2629", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "0.009", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S2674", + "shortDescription": { + "text": "The length returned from a stream read should be checked" + }, + "fullDescription": { + "text": "Invoking a stream reading method without verifying the number of bytes read can lead to erroneous assumptions. A Stream can represent any I/O operation, such as reading a file, network communication, or inter-process communication. As such, it is not guaranteed that the byte[] passed into the method will be filled with the requested number of bytes. Therefore, inspecting the value returned by the reading method is important to ensure the number of bytes read." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2674", + "properties": { + "category": "Minor Bug", + "executionTimeInSeconds": "0.013", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S2681", + "shortDescription": { + "text": "Multiline blocks should be enclosed in curly braces" + }, + "fullDescription": { + "text": "Having inconsistent indentation and omitting curly braces from a control structure, such as an if statement or for loop, is misleading and can induce bugs." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2681", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "0.020", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S2688", + "shortDescription": { + "text": "\"NaN\" should not be used in comparisons" + }, + "fullDescription": { + "text": "double.NaN and float.NaN are not equal to anything, not even themselves." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2688", + "properties": { + "category": "Major Bug", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S2692", + "shortDescription": { + "text": "\"IndexOf\" checks should not be for positive numbers" + }, + "fullDescription": { + "text": "Most checks against an IndexOf value compare it with -1 because 0 is a valid index." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2692", + "properties": { + "category": "Critical Code Smell", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S2696", + "shortDescription": { + "text": "Instance members should not write to \"static\" fields" + }, + "fullDescription": { + "text": "This rule raises an issue each time a static field is updated from a non-static method or property." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2696", + "properties": { + "category": "Critical Code Smell", + "executionTimeInSeconds": "0.005", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S2699", + "shortDescription": { + "text": "Tests should include assertions" + }, + "fullDescription": { + "text": "The rule targets test methods that lack an assertion and consist solely of an action and, optionally, a setup." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2699", + "properties": { + "category": "Blocker Code Smell", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S2701", + "shortDescription": { + "text": "Literal boolean values should not be used in assertions" + }, + "fullDescription": { + "text": "Using literal boolean values in assertions can lead to less readable and less informative unit tests. When a test fails, it’s important to have a clear understanding of what the test was checking and why it failed. Most of the testing frameworks provide more explicit assertion methods that will provide a more helpful error message if the test fails." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2701", + "properties": { + "category": "Critical Code Smell", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S2737", + "shortDescription": { + "text": "\"catch\" clauses should do more than rethrow" + }, + "fullDescription": { + "text": "A catch clause that only rethrows the caught exception has the same effect as omitting the catch altogether and letting it bubble up automatically." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2737", + "properties": { + "category": "Minor Code Smell", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S2743", + "shortDescription": { + "text": "Static fields should not be used in generic types" + }, + "fullDescription": { + "text": "A static field in a generic type is not shared among instances of different closed constructed types, thus LengthLimitedSingletonCollection.instances and LengthLimitedSingletonCollection.instances will point to different objects, even though instances is seemingly shared among all LengthLimitedSingletonCollection<> generic classes." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2743", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S2755", + "shortDescription": { + "text": "XML parsers should not be vulnerable to XXE attacks" + }, + "fullDescription": { + "text": "This vulnerability allows the usage of external entities in XML." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2755", + "properties": { + "category": "Blocker Vulnerability", + "executionTimeInSeconds": "0.020", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S2757", + "shortDescription": { + "text": "Non-existent operators like \"=+\" should not be used" + }, + "fullDescription": { + "text": "Using operator pairs (=+, =-, or =!) that look like reversed single operators (+=, -= or !=) is confusing. They compile and run but do not produce the same result as their mirrored counterpart." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2757", + "properties": { + "category": "Major Bug", + "executionTimeInSeconds": "0.004", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S2760", + "shortDescription": { + "text": "Sequential tests should not check the same condition" + }, + "fullDescription": { + "text": "When the same condition is checked twice in a row, it is either confusing - why have separate checks? - or an error - some other condition should have been checked in the second test." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2760", + "properties": { + "category": "Minor Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S2761", + "shortDescription": { + "text": "Doubled prefix operators \"!!\" and \"~~\" should not be used" + }, + "fullDescription": { + "text": "The repetition of a prefix operator (!, or ~) is usually a typo. The second operator invalidates the first one." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2761", + "properties": { + "category": "Major Bug", + "executionTimeInSeconds": "0.002", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S2857", + "shortDescription": { + "text": "SQL keywords should be delimited by whitespace" + }, + "fullDescription": { + "text": "When concatenating strings, it is very easy to forget a whitespace." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2857", + "properties": { + "category": "Blocker Bug", + "executionTimeInSeconds": "0.032", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S2925", + "shortDescription": { + "text": "\"Thread.Sleep\" should not be used in tests" + }, + "fullDescription": { + "text": "Using Thread.Sleep in a test might introduce unpredictable and inconsistent results depending on the environment. Furthermore, it will block the thread, which means the system resources are not being fully used." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2925", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S2930", + "shortDescription": { + "text": "\"IDisposables\" should be disposed" + }, + "fullDescription": { + "text": "When writing managed code, there is no need to worry about memory allocation or deallocation as it is taken care of by the garbage collector. However, certain objects, such as Bitmap, utilize unmanaged memory for specific purposes like pointer arithmetic. These objects may have substantial unmanaged memory footprints while having minimal managed footprints. Unfortunately, the garbage collector only recognizes the small managed footprint and does not promptly reclaim the corresponding unmanaged memory (by invoking the finalizer method of Bitmap) for efficiency reasons." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2930", + "properties": { + "category": "Blocker Bug", + "executionTimeInSeconds": "0.039", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S2931", + "shortDescription": { + "text": "Classes with \"IDisposable\" members should implement \"IDisposable\"" + }, + "fullDescription": { + "text": "An IDisposable object should be disposed (there are some rare exceptions where not disposing is fine, most notably Task). If a class has an IDisposable field, there can be two situations:" + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2931", + "properties": { + "category": "Blocker Bug", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S2933", + "shortDescription": { + "text": "Fields that are only assigned in the constructor should be \"readonly\"" + }, + "fullDescription": { + "text": "readonly fields can only be assigned in a class constructor. If a class has a field that’s not marked readonly but is only set in the constructor, it could cause confusion about the field’s intended use. To avoid confusion, such fields should be marked readonly to make their intended use explicit, and to prevent future maintainers from inadvertently changing their use." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2933", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "0.050", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S2934", + "shortDescription": { + "text": "Property assignments should not be made for \"readonly\" fields not constrained to reference types" + }, + "fullDescription": { + "text": "While the properties of a readonly reference type field can still be changed after initialization, those of a readonly value type field, such as a struct, cannot." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2934", + "properties": { + "category": "Minor Bug", + "executionTimeInSeconds": "0.003", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S2952", + "shortDescription": { + "text": "Classes should \"Dispose\" of members from the classes' own \"Dispose\" methods" + }, + "fullDescription": { + "text": "It is possible in an IDisposable to call Dispose on class members from any method, but the contract of Dispose is that it will clean up all unmanaged resources. Move disposing of members to some other method, and you risk resource leaks." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2952", + "properties": { + "category": "Critical Bug", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope" + ] + } + }, + { + "id": "S2953", + "shortDescription": { + "text": "Methods named \"Dispose\" should implement \"IDisposable.Dispose\"" + }, + "fullDescription": { + "text": "IDisposable is an interface implemented by all types which need to provide a mechanism for releasing unmanaged resources." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2953", + "properties": { + "category": "Blocker Code Smell", + "executionTimeInSeconds": "0.024", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S2955", + "shortDescription": { + "text": "Generic parameters not constrained to reference types should not be compared to \"null\"" + }, + "fullDescription": { + "text": "In C#, without constraints on a generic type parameter, both reference and value types can be passed. However, comparing this type parameter to null can be misleading as value types, like struct, can never be null." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2955", + "properties": { + "category": "Minor Bug", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S2970", + "shortDescription": { + "text": "Assertions should be complete" + }, + "fullDescription": { + "text": "This rule addresses the issue of incomplete assertions that can occur when using certain test frameworks. Incomplete assertions can lead to tests that do not effectively verify anything. The rule enforces the use of complete assertions in specific cases, namely:" + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2970", + "properties": { + "category": "Blocker Code Smell", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S2971", + "shortDescription": { + "text": "LINQ expressions should be simplified" + }, + "fullDescription": { + "text": "In the interests of readability, code that can be simplified should be simplified. To that end, there are several ways IEnumerable language integrated queries (LINQ) can be simplified. This not only improves readabilty but can also lead to improved performance." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2971", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "0.027", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S2995", + "shortDescription": { + "text": "\"Object.ReferenceEquals\" should not be used for value types" + }, + "fullDescription": { + "text": "In C#, the Object.ReferenceEquals method is used to compare two reference type variables. If you use this method to compare two value types, such as int, float, or bool you will not get the expected results because value type variables contain an instance of the type and not a reference to it." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2995", + "properties": { + "category": "Major Bug", + "executionTimeInSeconds": "0.006", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S2996", + "shortDescription": { + "text": "\"ThreadStatic\" fields should not be initialized" + }, + "fullDescription": { + "text": "When an object has a field annotated with ThreadStatic, that field is shared within a given thread, but unique across threads. Since a class' static initializer is only invoked for the first thread created, it also means that only the first thread will have the expected initial values." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2996", + "properties": { + "category": "Major Bug", + "executionTimeInSeconds": "0.002", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S2997", + "shortDescription": { + "text": "\"IDisposables\" created in a \"using\" statement should not be returned" + }, + "fullDescription": { + "text": "When you use a using statement, the goal is to ensure the correct disposal of an IDisposable instance when the control leaves the using statement block." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-2997", + "properties": { + "category": "Major Bug", + "executionTimeInSeconds": "0.024", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3005", + "shortDescription": { + "text": "\"ThreadStatic\" should not be used on non-static fields" + }, + "fullDescription": { + "text": "When you annotate a field with the ThreadStatic attribute, it is an indication that the value of this field is unique for each thread. But if you don’t mark the field as static, then the ThreadStatic attribute is ignored." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3005", + "properties": { + "category": "Major Bug", + "executionTimeInSeconds": "0.002", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3010", + "shortDescription": { + "text": "Static fields should not be updated in constructors" + }, + "fullDescription": { + "text": "Assigning a value to a static field in a constructor could cause unreliable behavior at runtime since it will change the value for all instances of the class." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3010", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "0.007", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3011", + "shortDescription": { + "text": "Reflection should not be used to increase accessibility of classes, methods, or fields" + }, + "fullDescription": { + "text": "Altering or bypassing the accessibility of classes, methods, or fields through reflection violates the encapsulation principle. This can break the internal contracts of the accessed target and lead to maintainability issues and runtime errors." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3011", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "0.124", + "executionTimeInPercentage": "2", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3052", + "shortDescription": { + "text": "Members should not be initialized to default values" + }, + "fullDescription": { + "text": "The compiler automatically initializes class fields, auto-properties and events to their default values before setting them with any initialization values, so there is no need to explicitly set a member to its default value. Further, under the logic that cleaner code is better code, it’s considered poor style to do so." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3052", + "properties": { + "category": "Minor Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S3059", + "shortDescription": { + "text": "Types should not have members with visibility set higher than the type's visibility" + }, + "fullDescription": { + "text": "There’s no point in having a public member in a non-public type because objects that can’t access the type will never have the chance to access the member." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3059", + "properties": { + "category": "Major Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope" + ] + } + }, + { + "id": "S3060", + "shortDescription": { + "text": "\"is\" should not be used with \"this\"" + }, + "fullDescription": { + "text": "One of the possible ways of performing type-testing is via the is operator: food is Pizza." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3060", + "properties": { + "category": "Blocker Code Smell", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3063", + "shortDescription": { + "text": "\"StringBuilder\" data should be used" + }, + "fullDescription": { + "text": "StringBuilder instances that never build a string clutter the code and worse are a drag on performance. Either they should be removed, or the missing ToString() call should be added." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3063", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "0.005", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3168", + "shortDescription": { + "text": "\"async\" methods should not return \"void\"" + }, + "fullDescription": { + "text": "An async method with a void return type does not follow the task asynchronous programming (TAP) model since the return type should be Task or Task" + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3168", + "properties": { + "category": "Major Bug", + "executionTimeInSeconds": "0.002", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3169", + "shortDescription": { + "text": "Multiple \"OrderBy\" calls should not be used" + }, + "fullDescription": { + "text": "There’s no point in chaining multiple OrderBy calls in a LINQ; only the last one will be reflected in the result because each subsequent call completely reorders the list. Thus, calling OrderBy multiple times is a performance issue as well, because all of the sorting will be executed, but only the result of the last sort will be kept." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3169", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "0.005", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3172", + "shortDescription": { + "text": "Delegates should not be subtracted" + }, + "fullDescription": { + "text": "In C#, delegates can be added together to chain their execution, and subtracted to remove their execution from the chain." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3172", + "properties": { + "category": "Major Bug", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3215", + "shortDescription": { + "text": "\"interface\" instances should not be cast to concrete types" + }, + "fullDescription": { + "text": "Needing to cast from an interface to a concrete type indicates that something is wrong with the abstractions in use, likely that something is missing from the interface. Instead of casting to a discrete type, the missing functionality should be added to the interface. Otherwise there is a risk of runtime exceptions." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3215", + "properties": { + "category": "Critical Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope" + ] + } + }, + { + "id": "S3216", + "shortDescription": { + "text": "\"ConfigureAwait(false)\" should be used" + }, + "fullDescription": { + "text": "After an awaited Task has executed, you can continue execution in the original, calling thread or any arbitrary thread. Unless the rest of the code needs the context from which the Task was spawned, Task.ConfigureAwait(false) should be used to keep execution in the Task thread to avoid the need for context switching and the possibility of deadlocks." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3216", + "properties": { + "category": "Critical Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope" + ] + } + }, + { + "id": "S3217", + "shortDescription": { + "text": "\"Explicit\" conversions of \"foreach\" loops should not be used" + }, + "fullDescription": { + "text": "The foreach statement was introduced in the C# language prior to generics to make it easier to work with the non-generic collections available at that time such as ArrayList. The foreach statements allow you to downcast elements of a collection of Objects to any other type." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3217", + "properties": { + "category": "Critical Code Smell", + "executionTimeInSeconds": "0.005", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3218", + "shortDescription": { + "text": "Inner class members should not shadow outer class \"static\" or type members" + }, + "fullDescription": { + "text": "Naming the members of an inner class the same as the static members of its enclosing class is possible but generally considered a bad practice. That’s because maintainers may be confused about which members are being used in a given context. Instead the inner class member should be given distinct and descriptive name, and all references to it should be updated accordingly." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3218", + "properties": { + "category": "Critical Code Smell", + "executionTimeInSeconds": "0.004", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3220", + "shortDescription": { + "text": "Method calls should not resolve ambiguously to overloads with \"params\"" + }, + "fullDescription": { + "text": "The rules for method resolution are complex and perhaps not properly understood by all coders. The params keyword can make method declarations overlap in non-obvious ways, so that slight changes in the argument types of an invocation can resolve to different methods." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3220", + "properties": { + "category": "Minor Code Smell", + "executionTimeInSeconds": "0.020", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3234", + "shortDescription": { + "text": "\"GC.SuppressFinalize\" should not be invoked for types without destructors" + }, + "fullDescription": { + "text": "GC.SuppressFinalize asks the Common Language Runtime not to call the finalizer of an object. This is useful when implementing the dispose pattern where object finalization is already handled in IDisposable.Dispose. However, it has no effect if there is no finalizer defined in the object’s type, so using it in such cases is just confusing." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3234", + "properties": { + "category": "Minor Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S3235", + "shortDescription": { + "text": "Redundant parentheses should not be used" + }, + "fullDescription": { + "text": "Redundant parentheses are simply wasted keystrokes, and should be removed." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3235", + "properties": { + "category": "Minor Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S3236", + "shortDescription": { + "text": "Caller information arguments should not be provided explicitly" + }, + "fullDescription": { + "text": "Caller information attributes: CallerFilePathAttribute, CallerLineNumberAttribute, and CallerArgumentExpressionAttribute provide a way to get information about the caller of a method through optional parameters. But the arguments for these optional parameters are only generated if they are not explicitly defined in the call. Thus, specifying the argument values defeats the purpose of the attributes." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3236", + "properties": { + "category": "Minor Code Smell", + "executionTimeInSeconds": "0.047", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3237", + "shortDescription": { + "text": "\"value\" contextual keyword should be used" + }, + "fullDescription": { + "text": "When you need to get external input for set and init methods defined for properties and indexers or for remove and add methods for events, you should always get this input throught the value contextual keyword." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3237", + "properties": { + "category": "Blocker Code Smell", + "executionTimeInSeconds": "0.003", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3240", + "shortDescription": { + "text": "The simplest possible condition syntax should be used" + }, + "fullDescription": { + "text": "In the interests of keeping code clean, the simplest possible conditional syntax should be used. That means" + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3240", + "properties": { + "category": "Minor Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S3241", + "shortDescription": { + "text": "Methods should not return values that are never used" + }, + "fullDescription": { + "text": "Private methods are intended for use only within their scope. If these methods return values that are not utilized by any calling functions, it indicates that the return operation is unnecessary. Removing such returns can enhance both efficiency and code clarity." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3241", + "properties": { + "category": "Minor Code Smell", + "executionTimeInSeconds": "0.031", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3242", + "shortDescription": { + "text": "Method parameters should be declared with base types" + }, + "fullDescription": { + "text": "When a derived type is used as a parameter instead of the base type, it limits the uses of the method. If the additional functionality that is provided in the derived type is not required then that limitation isn’t required, and should be removed." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3242", + "properties": { + "category": "Minor Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S3244", + "shortDescription": { + "text": "Anonymous delegates should not be used to unsubscribe from Events" + }, + "fullDescription": { + "text": "When working with anonymous functions, it is important to keep in mind that each time you create one, it is a completely new instance." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3244", + "properties": { + "category": "Major Bug", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3246", + "shortDescription": { + "text": "Generic type parameters should be co/contravariant when possible" + }, + "fullDescription": { + "text": "In the interests of making code as usable as possible, interfaces and delegates with generic parameters should use the out and in modifiers when possible to make the interfaces and delegates covariant and contravariant, respectively." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3246", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "0.010", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3247", + "shortDescription": { + "text": "Duplicate casts should not be made" + }, + "fullDescription": { + "text": "In C#, the is type testing operator can be used to check if the run-time type of an object is compatible with a given type. If the object is not null, then the is operator performs a cast, and so performing another cast following the check result is redundant." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3247", + "properties": { + "category": "Minor Code Smell", + "executionTimeInSeconds": "0.026", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3249", + "shortDescription": { + "text": "Classes directly extending \"object\" should not call \"base\" in \"GetHashCode\" or \"Equals\"" + }, + "fullDescription": { + "text": "Making a base call when overriding a method is generally a good idea, but not in the case of GetHashCode and Equals for classes that directly extend Object. These methods are based on the object’s reference, meaning that no two objects that use those base methods can be equal or have the same hash." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3249", + "properties": { + "category": "Major Bug", + "executionTimeInSeconds": "0.011", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3251", + "shortDescription": { + "text": "Implementations should be provided for \"partial\" methods" + }, + "fullDescription": { + "text": "partial methods allow an increased degree of flexibility in programming a system. Hooks can be added to generated code by invoking methods that define their signature, but might not have an implementation yet. But if the implementation is still missing when the code makes it to production, the compiler silently removes the call. In the best case scenario, such calls simply represent cruft, but in they worst case they are critical, missing functionality, the loss of which will lead to unexpected results at runtime." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3251", + "properties": { + "category": "Minor Code Smell", + "executionTimeInSeconds": "0.023", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3253", + "shortDescription": { + "text": "Constructor and destructor declarations should not be redundant" + }, + "fullDescription": { + "text": "Since the compiler will automatically invoke the base type’s no-argument constructor, there’s no need to specify its invocation explicitly. Also, when only a single public parameterless constructor is defined in a class, then that constructor can be removed because the compiler would generate it automatically. Similarly, empty static constructors and empty destructors are also wasted keystrokes." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3253", + "properties": { + "category": "Minor Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S3254", + "shortDescription": { + "text": "Default parameter values should not be passed as arguments" + }, + "fullDescription": { + "text": "Specifying the default parameter values in a method call is redundant. Such values should be omitted in the interests of readability." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3254", + "properties": { + "category": "Minor Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope" + ] + } + }, + { + "id": "S3256", + "shortDescription": { + "text": "\"string.IsNullOrEmpty\" should be used" + }, + "fullDescription": { + "text": "Using string.Equals to determine if a string is empty is significantly slower than using string.IsNullOrEmpty() or checking for string.Length == 0. string.IsNullOrEmpty() is both clear and concise, and therefore preferred to laborious, error-prone, manual null- and emptiness-checking." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3256", + "properties": { + "category": "Minor Code Smell", + "executionTimeInSeconds": "0.011", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3257", + "shortDescription": { + "text": "Declarations and initializations should be as concise as possible" + }, + "fullDescription": { + "text": "In C#, the type of a variable can often be inferred by the compiler. The use of the [var keyword](https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/implicitly-typed-local-variables) allows you to avoid repeating the type name in a variable declaration and object instantiation because the declared type can often be inferred by the compiler." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3257", + "properties": { + "category": "Minor Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S3260", + "shortDescription": { + "text": "Non-derived \"private\" classes and records should be \"sealed\"" + }, + "fullDescription": { + "text": "Classes and records with either private or file access modifiers aren’t visible outside of their assemblies or files, so if they’re not extended inside their scope, they should be made explicitly non-extensible with the addition of the sealed keyword." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3260", + "properties": { + "category": "Minor Code Smell", + "executionTimeInSeconds": "0.020", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3261", + "shortDescription": { + "text": "Namespaces should not be empty" + }, + "fullDescription": { + "text": "Namespaces with no lines of code clutter a project and should be removed." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3261", + "properties": { + "category": "Minor Code Smell", + "executionTimeInSeconds": "0.041", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3262", + "shortDescription": { + "text": "\"params\" should be used on overrides" + }, + "fullDescription": { + "text": "Overriding methods automatically inherit the params behavior. To ease readability, this modifier should be explicitly used in the overriding method as well." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3262", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "0.005", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3263", + "shortDescription": { + "text": "Static fields should appear in the order they must be initialized " + }, + "fullDescription": { + "text": "Static field initializers are executed in the order in which they appear in the class from top to bottom. Thus, placing a static field in a class above the field or fields required for its initialization will yield unexpected results." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3263", + "properties": { + "category": "Major Bug", + "executionTimeInSeconds": "0.002", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3264", + "shortDescription": { + "text": "Events should be invoked" + }, + "fullDescription": { + "text": "Events that are not invoked anywhere are dead code, and there’s no good reason to keep them in the source." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3264", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "0.011", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3265", + "shortDescription": { + "text": "Non-flags enums should not be used in bitwise operations" + }, + "fullDescription": { + "text": "Enumerations are commonly used to identify distinct elements from a set of values." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3265", + "properties": { + "category": "Critical Code Smell", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3267", + "shortDescription": { + "text": "Loops should be simplified with \"LINQ\" expressions" + }, + "fullDescription": { + "text": "When a loop is filtering, selecting or aggregating, those functions can be handled with a clearer, more concise LINQ expression instead." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3267", + "properties": { + "category": "Minor Code Smell", + "executionTimeInSeconds": "0.007", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3330", + "shortDescription": { + "text": "Creating cookies without the \"HttpOnly\" flag is security-sensitive" + }, + "fullDescription": { + "text": "When a cookie is configured with the HttpOnly attribute set to true, the browser guaranties that no client-side script will be able to read it. In most cases, when a cookie is created, the default value of HttpOnly is false and it’s up to the developer to decide whether or not the content of the cookie can be read by the client-side script. As a majority of Cross-Site Scripting (XSS) attacks target the theft of session-cookies, the HttpOnly attribute can help to reduce their impact as it won’t be possible to exploit the XSS vulnerability to steal session-cookies." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3330", + "properties": { + "category": "Minor Security Hotspot", + "executionTimeInSeconds": "0.002", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3343", + "shortDescription": { + "text": "Caller information parameters should come at the end of the parameter list" + }, + "fullDescription": { + "text": "Caller information attributes provide a way to get information about the caller of a method through optional parameters. But they only work right if their values aren’t provided explicitly. So if you define a method with caller info attributes in the middle of the parameter list, the caller is forced to use named arguments if they want to use the method properly." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3343", + "properties": { + "category": "Major Bug", + "executionTimeInSeconds": "0.035", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3346", + "shortDescription": { + "text": "Expressions used in \"Debug.Assert\" should not produce side effects" + }, + "fullDescription": { + "text": "An assertion is a piece of code that’s used during development when the compilation debug mode is activated. It allows a program to check itself as it runs. When an assertion is true, that means everything is operating as expected." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3346", + "properties": { + "category": "Major Bug", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3353", + "shortDescription": { + "text": "Unchanged variables should be marked as \"const\"" + }, + "fullDescription": { + "text": "If a variable that is not supposed to change is not marked as const, it could be accidentally reassigned elsewhere in the code, leading to unexpected behavior and bugs that can be hard to track down." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3353", + "properties": { + "category": "Critical Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope" + ] + } + }, + { + "id": "S3358", + "shortDescription": { + "text": "Ternary operators should not be nested" + }, + "fullDescription": { + "text": "Nested ternaries are hard to read and can make the order of operations complex to understand." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3358", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "0.002", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3363", + "shortDescription": { + "text": "Date and time should not be used as a type for primary keys" + }, + "fullDescription": { + "text": "You should only set a property of a temporal type (like DateTime or DateTimeOffset) as the primary key of a table if the values are guaranteed to be unique." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3363", + "properties": { + "category": "Minor Bug", + "executionTimeInSeconds": "0.016", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3366", + "shortDescription": { + "text": "\"this\" should not be exposed from constructors" + }, + "fullDescription": { + "text": "In single-threaded environments, the use of this in constructors is normal, and expected. But in multi-threaded environments, it could expose partially-constructed objects to other threads, and should be used with caution." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3366", + "properties": { + "category": "Major Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope" + ] + } + }, + { + "id": "S3376", + "shortDescription": { + "text": "Attribute, EventArgs, and Exception type names should end with the type being extended" + }, + "fullDescription": { + "text": "Adherence to the standard naming conventions makes your code not only more readable, but more usable. For instance, class FirstAttribute : Attribute can be used simply with First, but you must use the full name for class AttributeOne : Attribute." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3376", + "properties": { + "category": "Minor Code Smell", + "executionTimeInSeconds": "0.006", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3397", + "shortDescription": { + "text": "\"base.Equals\" should not be used to check for reference equality in \"Equals\" if \"base\" is not \"object\"" + }, + "fullDescription": { + "text": "object.Equals() overrides can be optimized by checking first for reference equality between this and the parameter. This check can be implemented by calling object.ReferenceEquals() or base.Equals(), where base is object. However, using base.Equals() is a maintenance hazard because while it works if you extend Object directly, if you introduce a new base class that overrides Equals, it suddenly stops working." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3397", + "properties": { + "category": "Minor Bug", + "executionTimeInSeconds": "0.003", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3398", + "shortDescription": { + "text": "\"private\" methods called only by inner classes should be moved to those classes" + }, + "fullDescription": { + "text": "When a private static method is only invoked by a nested class, there’s no reason not to move it into that class. It will still have the same access to the outer class' static members, but the outer class will be clearer and less cluttered." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3398", + "properties": { + "category": "Minor Code Smell", + "executionTimeInSeconds": "0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3400", + "shortDescription": { + "text": "Methods should not return constants" + }, + "fullDescription": { + "text": "There’s no point in forcing the overhead of a method call for a method that always returns the same constant value. Even worse, the fact that a method call must be made will likely mislead developers who call the method thinking that something more is done. Declare a constant instead." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3400", + "properties": { + "category": "Minor Code Smell", + "executionTimeInSeconds": "0.023", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3415", + "shortDescription": { + "text": "Assertion arguments should be passed in the correct order" + }, + "fullDescription": { + "text": "The standard assertions library methods such as AreEqual and AreSame in MSTest and NUnit, or Equal and Same in XUnit, expect the first argument to be the expected value and the second argument to be the actual value." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3415", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3416", + "shortDescription": { + "text": "Loggers should be named for their enclosing types" + }, + "fullDescription": { + "text": "It is a well-established convention to name each logger after its enclosing type. This rule raises an issue when the convention is not respected." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3416", + "properties": { + "category": "Minor Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope" + ] + } + }, + { + "id": "S3427", + "shortDescription": { + "text": "Method overloads with default parameter values should not overlap" + }, + "fullDescription": { + "text": "The rules for method resolution can be complex and may not be fully understood by all developers. The situation becomes even more challenging when dealing with method overloads that have optional parameter values." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3427", + "properties": { + "category": "Blocker Code Smell", + "executionTimeInSeconds": "0.003", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3431", + "shortDescription": { + "text": "\"[ExpectedException]\" should not be used" + }, + "fullDescription": { + "text": "It should be clear to a casual reader what code a test is testing and what results are expected. Unfortunately, that’s not usually the case with the ExpectedException attribute since an exception could be thrown from almost any line in the method." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3431", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3433", + "shortDescription": { + "text": "Test method signatures should be correct" + }, + "fullDescription": { + "text": "A method is identified as a test method if it is marked with one of the following attributes:" + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3433", + "properties": { + "category": "Blocker Code Smell", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3440", + "shortDescription": { + "text": "Variables should not be checked against the values they're about to be assigned" + }, + "fullDescription": { + "text": "There’s no point in checking a variable against the value you’re about to assign it. Save the cycles and lines of code, and simply perform the assignment." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3440", + "properties": { + "category": "Minor Code Smell", + "executionTimeInSeconds": "0.003", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3441", + "shortDescription": { + "text": "Redundant property names should be omitted in anonymous classes" + }, + "fullDescription": { + "text": "When an anonymous type’s properties are copied from properties or variables with the same names, it yields cleaner code to omit the new type’s property name and the assignment operator." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3441", + "properties": { + "category": "Minor Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S3442", + "shortDescription": { + "text": "\"abstract\" classes should not have \"public\" constructors" + }, + "fullDescription": { + "text": "The abstract modifier in a class declaration is used to indicate that a class is intended only to be a base class of other classes, not instantiated on its own." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3442", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "0.007", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3443", + "shortDescription": { + "text": "Type should not be examined on \"System.Type\" instances" + }, + "fullDescription": { + "text": "Calling GetType on a Type variable will always return the System.Type representation, which is equivalent to typeof(System.Type). This also applies to passing a Type argument to IsInstanceOfType which always returns false." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3443", + "properties": { + "category": "Blocker Code Smell", + "executionTimeInSeconds": "0.005", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3444", + "shortDescription": { + "text": "Interfaces should not simply inherit from base interfaces with colliding members" + }, + "fullDescription": { + "text": "When an interface inherits from two interfaces that both define a member with the same name, trying to access that member through the derived interface will result in the compiler error CS0229 Ambiguity between 'IBase1.SomeProperty' and 'IBase2.SomeProperty'." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3444", + "properties": { + "category": "Minor Code Smell", + "executionTimeInSeconds": "0.007", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3445", + "shortDescription": { + "text": "Exceptions should not be explicitly rethrown" + }, + "fullDescription": { + "text": "In C#, the throw statement can be used in two different ways:" + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3445", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3447", + "shortDescription": { + "text": "\"[Optional]\" should not be used on \"ref\" or \"out\" parameters" + }, + "fullDescription": { + "text": "The use of ref or out in combination with Optional attribute is both confusing and contradictory. [Optional] indicates that the parameter doesn’t have to be provided, while out and ref mean that the parameter will be used to return data to the caller (ref additionally indicates that the parameter may also be used to pass data into the method)." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3447", + "properties": { + "category": "Critical Code Smell", + "executionTimeInSeconds": "0.011", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3449", + "shortDescription": { + "text": "Right operands of shift operators should be integers" + }, + "fullDescription": { + "text": "Numbers can be shifted with the << and >> operators, but the right operand of the operation needs to be an int or a type that has an implicit conversion to int. However, when the left operand is dynamic, the compiler’s type checking is turned off, so you can pass anything to the right of a shift operator and have it compile. And if the argument can’t be implicitly converted to int at runtime, then a RuntimeBinderException will be raised." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3449", + "properties": { + "category": "Critical Bug", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3450", + "shortDescription": { + "text": "Parameters with \"[DefaultParameterValue]\" attributes should also be marked \"[Optional]\"" + }, + "fullDescription": { + "text": "There is no point in providing a default value for a parameter if callers are required to provide a value for it anyway. Thus, [DefaultParameterValue] should always be used in conjunction with [Optional]." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3450", + "properties": { + "category": "Minor Code Smell", + "executionTimeInSeconds": "0.007", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3451", + "shortDescription": { + "text": "\"[DefaultValue]\" should not be used when \"[DefaultParameterValue]\" is meant" + }, + "fullDescription": { + "text": "DefaultValue does not make the compiler set the default value, as its name may suggest. What you probably wanted to use is DefaultParameterValue." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3451", + "properties": { + "category": "Critical Code Smell", + "executionTimeInSeconds": "0.009", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3453", + "shortDescription": { + "text": "Classes should not have only \"private\" constructors" + }, + "fullDescription": { + "text": "When a class has only a private constructor, it can’t be instantiated except within the class itself. Such classes can be considered dead code and should be fixed" + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3453", + "properties": { + "category": "Major Bug", + "executionTimeInSeconds": "0.019", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3456", + "shortDescription": { + "text": "\"string.ToCharArray()\" and \"ReadOnlySpan.ToArray()\" should not be called redundantly" + }, + "fullDescription": { + "text": "The string type offers an indexer property that allows you to treat it as a char array. Therefore, if you just need to access a specific character or iterate over all of them, the ToCharArray call should be omitted. For these cases, not omitting makes the code harder to read and less efficient as ToCharArray copies the characters from the string object into a new Unicode character array." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3456", + "properties": { + "category": "Minor Bug", + "executionTimeInSeconds": "0.003", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3457", + "shortDescription": { + "text": "Composite format strings should be used correctly" + }, + "fullDescription": { + "text": "A composite format string is a string that contains placeholders, represented by indices inside curly braces \"{0}\", \"{1}\", etc. These placeholders are replaced by values when the string is printed or logged." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3457", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "0.012", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3458", + "shortDescription": { + "text": "Empty \"case\" clauses that fall through to the \"default\" should be omitted" + }, + "fullDescription": { + "text": "Empty case clauses that fall through to the default are useless. Whether or not such a case is present, the default clause will be invoked. Such cases simply clutter the code, and should be removed." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3458", + "properties": { + "category": "Minor Code Smell", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3459", + "shortDescription": { + "text": "Unassigned members should be removed" + }, + "fullDescription": { + "text": "Fields and auto-properties that are never assigned to hold the default values for their types. They are either pointless code or, more likely, mistakes." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3459", + "properties": { + "category": "Minor Code Smell", + "executionTimeInSeconds": "0.047", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3464", + "shortDescription": { + "text": "Type inheritance should not be recursive" + }, + "fullDescription": { + "text": "Recursion is a technique used to define a problem in terms of the problem itself, usually in terms of a simpler version of the problem itself." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3464", + "properties": { + "category": "Blocker Bug", + "executionTimeInSeconds": "0.005", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3466", + "shortDescription": { + "text": "Optional parameters should be passed to \"base\" calls" + }, + "fullDescription": { + "text": "When optional parameter values are not passed to base method calls, the value passed in by the caller is ignored. This can cause the function to behave differently than expected, leading to errors and making the code difficult to debug." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3466", + "properties": { + "category": "Major Bug", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3532", + "shortDescription": { + "text": "Empty \"default\" clauses should be removed" + }, + "fullDescription": { + "text": "The default clause should take appropriate action. Having an empty default is a waste of keystrokes." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3532", + "properties": { + "category": "Minor Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S3597", + "shortDescription": { + "text": "\"ServiceContract\" and \"OperationContract\" attributes should be used together" + }, + "fullDescription": { + "text": "The ServiceContract attribute specifies that a class or interface defines the communication contract of a Windows Communication Foundation (WCF) service. The service operations of this class or interface are defined by OperationContract attributes added to methods. It doesn’t make sense to define a contract without any service operations; thus, in a ServiceContract class or interface at least one method should be annotated with OperationContract. Similarly, WCF only serves OperationContract methods that are defined inside ServiceContract classes or interfaces; thus, this rule also checks that ServiceContract is added to the containing type of OperationContract methods." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3597", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "0.003", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3598", + "shortDescription": { + "text": "One-way \"OperationContract\" methods should have \"void\" return type" + }, + "fullDescription": { + "text": "When declaring a Windows Communication Foundation (WCF) OperationContract method as one-way, that service method won’t return any result, not even an underlying empty confirmation message. These are fire-and-forget methods that are useful in event-like communication. Therefore, specifying a return type has no effect and can confuse readers." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3598", + "properties": { + "category": "Major Bug", + "executionTimeInSeconds": "0.060", + "executionTimeInPercentage": "1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3600", + "shortDescription": { + "text": "\"params\" should not be introduced on overrides" + }, + "fullDescription": { + "text": "Adding params to a method override has no effect. The compiler accepts it, but the callers won’t be able to benefit from the added modifier." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3600", + "properties": { + "category": "Critical Code Smell", + "executionTimeInSeconds": "0.016", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3603", + "shortDescription": { + "text": "Methods with \"Pure\" attribute should return a value " + }, + "fullDescription": { + "text": "Marking a method with the Pure attribute indicates that the method doesn’t make any visible state changes. Therefore, a Pure method should return a result. Otherwise, it indicates a no-operation call." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3603", + "properties": { + "category": "Major Bug", + "executionTimeInSeconds": "0.004", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3604", + "shortDescription": { + "text": "Member initializer values should not be redundant" + }, + "fullDescription": { + "text": "Fields, properties and events can be initialized either inline or in the constructor. Initializing them inline and in the constructor at the same time is redundant; the inline initialization will be overridden." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3604", + "properties": { + "category": "Minor Code Smell", + "executionTimeInSeconds": "0.057", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3610", + "shortDescription": { + "text": "Nullable type comparison should not be redundant" + }, + "fullDescription": { + "text": "Calling GetType() on a nullable value type object returns the underlying value type. Therefore, comparing the returned Type object to typeof(Nullable) will either throw an NullReferenceException or the result will always be true or false and can be known at compile time." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3610", + "properties": { + "category": "Major Bug", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3626", + "shortDescription": { + "text": "Jump statements should not be redundant" + }, + "fullDescription": { + "text": "Jump statements, such as return, yield break, goto, and continue let you change the default flow of program execution, but jump statements that direct the control flow to the original direction are just a waste of keystrokes." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3626", + "properties": { + "category": "Minor Code Smell", + "executionTimeInSeconds": "0.115", + "executionTimeInPercentage": "1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3717", + "shortDescription": { + "text": "Track use of \"NotImplementedException\"" + }, + "fullDescription": { + "text": "NotImplementedException is often used to mark methods which must be implemented for the overall functionality to be complete, but which the developer wants to implement later. That’s as opposed to the NotSupportedException which is thrown by methods which are required by base classes or interfaces, but which are not appropriate to the current class." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3717", + "properties": { + "category": "Minor Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S3776", + "shortDescription": { + "text": "Cognitive Complexity of methods should not be too high" + }, + "fullDescription": { + "text": "This rule raises an issue when the code cognitive complexity of a function is above a certain threshold." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3776", + "properties": { + "category": "Critical Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3869", + "shortDescription": { + "text": "\"SafeHandle.DangerousGetHandle\" should not be called" + }, + "fullDescription": { + "text": "The SafeHandle.DangerousGetHandle method poses significant risks and should be used carefully. This method carries the inherent danger of potentially returning an invalid handle, which can result in resource leaks and security vulnerabilities. Although it is technically possible to utilize this method without encountering issues, doing so correctly requires a high level of expertise. Therefore, it is recommended to avoid using this method altogether." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3869", + "properties": { + "category": "Blocker Bug", + "executionTimeInSeconds": "0.011", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3871", + "shortDescription": { + "text": "Exception types should be \"public\"" + }, + "fullDescription": { + "text": "The point of having custom exception types is to convey more information than is available in standard types. But custom exception types must be public for that to work." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3871", + "properties": { + "category": "Critical Code Smell", + "executionTimeInSeconds": "0.006", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3872", + "shortDescription": { + "text": "Parameter names should not duplicate the names of their methods" + }, + "fullDescription": { + "text": "The name of a method should communicate what it does, and the names of its parameters should indicate how they’re used. If a method and its parameter have the same name it is an indication that one of these rules of thumb has been broken, if not both. Even if by some trick of language that’s not the case, it is still likely to confuse callers and maintainers." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3872", + "properties": { + "category": "Minor Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S3874", + "shortDescription": { + "text": "\"out\" and \"ref\" parameters should not be used" + }, + "fullDescription": { + "text": "Passing a parameter by reference, which is what happens when you use the out or ref parameter modifiers, means that the method will receive a pointer to the argument, rather than the argument itself. If the argument was a value type, the method will be able to change the argument’s values. If it was a reference type, then the method receives a pointer to a pointer, which is usually not what was intended. Even when it is what was intended, this is the sort of thing that’s difficult to get right, and should be used with caution." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3874", + "properties": { + "category": "Critical Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S3875", + "shortDescription": { + "text": "\"operator==\" should not be overloaded on reference types" + }, + "fullDescription": { + "text": "The use of == to compare two objects is expected to do a reference comparison. That is, it is expected to return true if and only if they are the same object instance. Overloading the operator to do anything else will inevitably lead to the introduction of bugs by callers." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3875", + "properties": { + "category": "Blocker Code Smell", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3876", + "shortDescription": { + "text": "Strings or integral types should be used for indexers" + }, + "fullDescription": { + "text": "Strings and integral types are typically used as indexers. When some other type is required, it typically indicates design problems, and potentially a situation where a method should be used instead." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3876", + "properties": { + "category": "Minor Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S3877", + "shortDescription": { + "text": "Exceptions should not be thrown from unexpected methods" + }, + "fullDescription": { + "text": "The rule is reporting when an exception is thrown from certain methods and constructors. These methods are expected to behave in a specific way and throwing an exception from them can lead to unexpected behavior and break the calling code." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3877", + "properties": { + "category": "Blocker Code Smell", + "executionTimeInSeconds": "0.021", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3878", + "shortDescription": { + "text": "Arrays should not be created for params parameters" + }, + "fullDescription": { + "text": "Creating an array or using a collection expression solely for the purpose of passing it to a params parameter is unnecessary. Simply pass the elements directly, and they will be automatically consolidated into the appropriate collection type." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3878", + "properties": { + "category": "Minor Code Smell", + "executionTimeInSeconds": "0.097", + "executionTimeInPercentage": "1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3880", + "shortDescription": { + "text": "Finalizers should not be empty" + }, + "fullDescription": { + "text": "Finalizers come with a performance cost due to the overhead of tracking the life cycle of objects. An empty one is consequently costly with no benefit or justification." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3880", + "properties": { + "category": "Major Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S3881", + "shortDescription": { + "text": "\"IDisposable\" should be implemented correctly" + }, + "fullDescription": { + "text": "The IDisposable interface is a mechanism to release unmanaged resources, if not implemented correctly this could result in resource leaks or more severe bugs." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3881", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "0.015", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3884", + "shortDescription": { + "text": "\"CoSetProxyBlanket\" and \"CoInitializeSecurity\" should not be used" + }, + "fullDescription": { + "text": "This rule is deprecated, and will eventually be removed." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3884", + "properties": { + "category": "Blocker Vulnerability", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S3885", + "shortDescription": { + "text": "\"Assembly.Load\" should be used" + }, + "fullDescription": { + "text": "The parameter to Assembly.Load includes the full specification of the dll to be loaded. Use another method, and you might end up with a dll other than the one you expected." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3885", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3887", + "shortDescription": { + "text": "Mutable, non-private fields should not be \"readonly\"" + }, + "fullDescription": { + "text": "Using the readonly keyword on a field means it can’t be changed after initialization. However, that’s only partly true when applied to collections or arrays. The readonly keyword enforces that another instance can’t be assigned to the field, but it cannot keep the contents from being updated. In practice, the field value can be changed, and the use of readonly on such a field is misleading, and you’re likely not getting the behavior you expect." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3887", + "properties": { + "category": "Minor Bug", + "executionTimeInSeconds": "0.021", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3889", + "shortDescription": { + "text": "\"Thread.Resume\" and \"Thread.Suspend\" should not be used" + }, + "fullDescription": { + "text": "Thread.Suspend and Thread.Resume can give unpredictable results, and both methods have been deprecated. Indeed, if Thread.Suspend is not used very carefully, a thread can be suspended while holding a lock, thus leading to a deadlock." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3889", + "properties": { + "category": "Blocker Bug", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3897", + "shortDescription": { + "text": "Classes that provide \"Equals()\" should implement \"IEquatable\"" + }, + "fullDescription": { + "text": "The IEquatable interface has only one method in it: Equals(). If you’ve already written Equals(T), there’s no reason not to explicitly implement IEquatable. Doing so expands the utility of your class by allowing it to be used where an IEquatable is called for." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3897", + "properties": { + "category": "Minor Code Smell", + "executionTimeInSeconds": "0.006", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3898", + "shortDescription": { + "text": "Value types should implement \"IEquatable\"" + }, + "fullDescription": { + "text": "If you’re using a struct, it is likely because you’re interested in performance. But by failing to implement IEquatable you’re loosing performance when comparisons are made because without IEquatable, boxing and reflection are used to make comparisons." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3898", + "properties": { + "category": "Major Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S3902", + "shortDescription": { + "text": "\"Assembly.GetExecutingAssembly\" should not be called" + }, + "fullDescription": { + "text": "Using Type.Assembly to get the current assembly is nearly free in terms of performance; it’s a simple property access. On the other hand, Assembly.GetExecutingAssembly() can take up to 30 times as long because it walks up the call stack to find the assembly." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3902", + "properties": { + "category": "Major Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S3903", + "shortDescription": { + "text": "Types should be defined in named namespaces" + }, + "fullDescription": { + "text": "Types are declared in namespaces in order to prevent name collisions and as a way to organize them into the object hierarchy. Types that are defined outside any named namespace are in a global namespace that cannot be referenced in code." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3903", + "properties": { + "category": "Major Bug", + "executionTimeInSeconds": "0.002", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3904", + "shortDescription": { + "text": "Assemblies should have version information" + }, + "fullDescription": { + "text": "The AssemblyVersion attribute is used to specify the version number of an assembly. An assembly is a compiled unit of code, which can be marked with a version number by applying the attribute to an assembly’s source code file." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3904", + "properties": { + "category": "Critical Code Smell", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3906", + "shortDescription": { + "text": "Event Handlers should have the correct signature" + }, + "fullDescription": { + "text": "Delegate event handlers (i.e. delegates used as type of an event) should have a very specific signature:" + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3906", + "properties": { + "category": "Major Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S3908", + "shortDescription": { + "text": "Generic event handlers should be used" + }, + "fullDescription": { + "text": "Since .Net Framework version 2.0 it is not necessary to declare a delegate that specifies a class derived from System.EventArgs. The System.EventHandler delegate mechanism should be used instead as it allows any class derived from EventArgs to be used with that handler." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3908", + "properties": { + "category": "Major Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S3909", + "shortDescription": { + "text": "Collections should implement the generic interface" + }, + "fullDescription": { + "text": "The NET Framework 2.0 introduced the generic interface System.Collections.Generic.IEnumerable and it should be preferred over the older, non generic, interfaces." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3909", + "properties": { + "category": "Major Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S3923", + "shortDescription": { + "text": "All branches in a conditional structure should not have exactly the same implementation" + }, + "fullDescription": { + "text": "Having all branches of a switch or if chain with the same implementation indicates a problem." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3923", + "properties": { + "category": "Major Bug", + "executionTimeInSeconds": "0.004", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3925", + "shortDescription": { + "text": "\"ISerializable\" should be implemented correctly" + }, + "fullDescription": { + "text": "The ISerializable interface is the mechanism to control the type serialization process. If not implemented correctly this could result in an invalid serialization and hard-to-detect bugs." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3925", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "0.003", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3926", + "shortDescription": { + "text": "Deserialization methods should be provided for \"OptionalField\" members" + }, + "fullDescription": { + "text": "Fields marked with System.Runtime.Serialization.OptionalFieldAttribute are serialized just like any other field. But such fields are ignored on deserialization, and retain the default values associated with their types. Therefore, deserialization event handlers should be declared to set such fields during the deserialization process." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3926", + "properties": { + "category": "Major Bug", + "executionTimeInSeconds": "0.004", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3927", + "shortDescription": { + "text": "Serialization event handlers should be implemented correctly" + }, + "fullDescription": { + "text": "Serialization event handlers that don’t have the correct signature will not be called, bypassing augmentations to automated serialization and deserialization events." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3927", + "properties": { + "category": "Major Bug", + "executionTimeInSeconds": "0.013", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3928", + "shortDescription": { + "text": "Parameter names used into ArgumentException constructors should match an existing one " + }, + "fullDescription": { + "text": "Some constructors of the ArgumentException, ArgumentNullException, ArgumentOutOfRangeException and DuplicateWaitObjectException classes must be fed with a valid parameter name. This rule raises an issue in two cases:" + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3928", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "0.007", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3937", + "shortDescription": { + "text": "Number patterns should be regular" + }, + "fullDescription": { + "text": "The use of punctuation characters to separate subgroups in a number can make the number more readable. For instance consider 1,000,000,000 versus 1000000000. But when the grouping is irregular, such as 1,000,00,000; it indicates an error." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3937", + "properties": { + "category": "Critical Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S3956", + "shortDescription": { + "text": "\"Generic.List\" instances should not be part of public APIs" + }, + "fullDescription": { + "text": "System.Collections.Generic.List is a generic collection that is designed for performance and not inheritance. For example, it does not contain virtual members that make it easier to change the behavior of an inherited class. That means that future attempts to expand the behavior will be spoiled because the extension points simply aren’t there. Instead, one of the following generic collections should be used:" + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3956", + "properties": { + "category": "Major Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope" + ] + } + }, + { + "id": "S3962", + "shortDescription": { + "text": "\"static readonly\" constants should be \"const\" instead" + }, + "fullDescription": { + "text": "The value of a static readonly field is computed at runtime while the value of a const field is calculated at compile time, which improves performance." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3962", + "properties": { + "category": "Minor Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S3963", + "shortDescription": { + "text": "\"static\" fields should be initialized inline" + }, + "fullDescription": { + "text": "When a static constructor serves no other purpose that initializing static fields, it comes with an unnecessary performance cost because the compiler generates a check before each static method or instance constructor invocation." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3963", + "properties": { + "category": "Minor Code Smell", + "executionTimeInSeconds": "0.012", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3967", + "shortDescription": { + "text": "Multidimensional arrays should not be used" + }, + "fullDescription": { + "text": "A jagged array is an array whose elements are arrays. It is recommended over a multidimensional array because the arrays that make up the elements can be of different sizes, which avoids wasting memory space." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3967", + "properties": { + "category": "Minor Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S3971", + "shortDescription": { + "text": "\"GC.SuppressFinalize\" should not be called" + }, + "fullDescription": { + "text": "GC.SuppressFinalize requests that the system not call the finalizer for the specified object. This should only be done when implementing Dispose as part of the Dispose Pattern." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3971", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3972", + "shortDescription": { + "text": "Conditionals should start on new lines" + }, + "fullDescription": { + "text": "Placing an if statement on the same line as the closing } from a preceding if, else, or else if block can lead to confusion and potential errors. It may indicate a missing else statement or create ambiguity for maintainers who might fail to understand that the two statements are unconnected." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3972", + "properties": { + "category": "Critical Code Smell", + "executionTimeInSeconds": "0.004", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3973", + "shortDescription": { + "text": "A conditionally executed single line should be denoted by indentation" + }, + "fullDescription": { + "text": "When the line immediately after conditional statements has neither curly braces nor indentation, the intent of the code is unclear and perhaps not executed as expected. Additionally, such code is confusing to maintainers." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3973", + "properties": { + "category": "Critical Code Smell", + "executionTimeInSeconds": "0.006", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3981", + "shortDescription": { + "text": "Collection sizes and array length comparisons should make sense" + }, + "fullDescription": { + "text": "The size of a collection and the length of an array are always greater than or equal to zero. Testing it doesn’t make sense, since the result is always true." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3981", + "properties": { + "category": "Major Bug", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3984", + "shortDescription": { + "text": "Exceptions should not be created without being thrown" + }, + "fullDescription": { + "text": "Creating a new Exception without actually throwing does not achieve the intended purpose." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3984", + "properties": { + "category": "Major Bug", + "executionTimeInSeconds": "0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3990", + "shortDescription": { + "text": "Assemblies should be marked as CLS compliant" + }, + "fullDescription": { + "text": "Assemblies should conform with the Common Language Specification (CLS) in order to be usable across programming languages. To be compliant an assembly has to indicate it with System.CLSCompliantAttribute." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3990", + "properties": { + "category": "Major Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S3992", + "shortDescription": { + "text": "Assemblies should explicitly specify COM visibility" + }, + "fullDescription": { + "text": "Assemblies should explicitly indicate whether they are meant to be COM visible or not. If the ComVisibleAttribute is not present, the default is to make the content of the assembly visible to COM clients." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3992", + "properties": { + "category": "Major Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S3993", + "shortDescription": { + "text": "Custom attributes should be marked with \"System.AttributeUsageAttribute\"" + }, + "fullDescription": { + "text": "When defining custom attributes, AttributeUsageAttribute must be used to indicate where the attribute can be applied. This will:" + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3993", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "0.002", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S3994", + "shortDescription": { + "text": "URI Parameters should not be strings" + }, + "fullDescription": { + "text": "String representations of URIs or URLs are prone to parsing and encoding errors which can lead to vulnerabilities. The System.Uri class is a safe alternative and should be preferred. At minimum, an overload of the method taking a System.Uri as a parameter should be provided in each class that contains a method with an apparent Uri passed as a string." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3994", + "properties": { + "category": "Major Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S3995", + "shortDescription": { + "text": "URI return values should not be strings" + }, + "fullDescription": { + "text": "String representations of URIs or URLs are prone to parsing and encoding errors which can lead to vulnerabilities. The System.Uri class is a safe alternative and should be preferred." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3995", + "properties": { + "category": "Major Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S3996", + "shortDescription": { + "text": "URI properties should not be strings" + }, + "fullDescription": { + "text": "String representations of URIs or URLs are prone to parsing and encoding errors which can lead to vulnerabilities. The System.Uri class is a safe alternative and should be preferred." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3996", + "properties": { + "category": "Major Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S3997", + "shortDescription": { + "text": "String URI overloads should call \"System.Uri\" overloads" + }, + "fullDescription": { + "text": "String representations of URIs or URLs are prone to parsing and encoding errors which can lead to vulnerabilities. The System.Uri class is a safe alternative and should be preferred." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3997", + "properties": { + "category": "Major Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S3998", + "shortDescription": { + "text": "Threads should not lock on objects with weak identity" + }, + "fullDescription": { + "text": "Objects that can be accessed across application domain boundaries are said to have weak identity. This means that these objects can be considered shared resources outside of the domain, which can be lead to them being accessed or modified by multiple threads or concurrent parts of a program, outside of the domain." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-3998", + "properties": { + "category": "Critical Code Smell", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S4000", + "shortDescription": { + "text": "Pointers to unmanaged memory should not be visible" + }, + "fullDescription": { + "text": "Pointer and unmanaged function pointer types such as IntPtr, UIntPtr, int* etc. are used to access unmanaged memory, usually in order to use C or C++ libraries. If such a pointer is not secured by making it private, internal or readonly, it can lead to a vulnerability allowing access to arbitrary locations." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-4000", + "properties": { + "category": "Critical Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S4002", + "shortDescription": { + "text": "Disposable types should declare finalizers" + }, + "fullDescription": { + "text": "This rule raises an issue when a disposable type contains fields of the following types and does not implement a finalizer:" + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-4002", + "properties": { + "category": "Major Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S4004", + "shortDescription": { + "text": "Collection properties should be readonly" + }, + "fullDescription": { + "text": "A writable collection property can be replaced by a completely different collection. Making it readonly prevents that while still allowing individual members to be set. If you want to allow the replacement of the whole collection the recommended pattern is to implement a method to remove all the elements (e.g. System.Collections.List.Clear) and a method to populate the collection (e.g. System.Collections.List.AddRange)." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-4004", + "properties": { + "category": "Major Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S4005", + "shortDescription": { + "text": "\"System.Uri\" arguments should be used instead of strings" + }, + "fullDescription": { + "text": "String representations of URIs or URLs are prone to parsing and encoding errors which can lead to vulnerabilities. The System.Uri class is a safe alternative and should be preferred." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-4005", + "properties": { + "category": "Major Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S4015", + "shortDescription": { + "text": "Inherited member visibility should not be decreased" + }, + "fullDescription": { + "text": "Decreasing the accessibility level of an inherited method that is not overridable to private will shadow the name of the base method and can lead to confusion." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-4015", + "properties": { + "category": "Critical Code Smell", + "executionTimeInSeconds": "0.016", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S4016", + "shortDescription": { + "text": "Enumeration members should not be named \"Reserved\"" + }, + "fullDescription": { + "text": "If an enum member’s name contains the word \"reserved\" it implies it is not currently used and will be change in the future. However changing an enum member is a breaking change and can create significant problems. There is no need to reserve an enum member since a new member can be added in the future, and such an addition will usually not be a breaking change." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-4016", + "properties": { + "category": "Major Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S4017", + "shortDescription": { + "text": "Method signatures should not contain nested generic types" + }, + "fullDescription": { + "text": "A nested type is a type argument that is also a generic type. Calling a method with such a nested type argument requires complicated and confusing code. It should be avoided as much as possible." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-4017", + "properties": { + "category": "Major Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S4018", + "shortDescription": { + "text": "All type parameters should be used in the parameter list to enable type inference" + }, + "fullDescription": { + "text": "Type inference enables the call of a generic method without explicitly specifying its type arguments. This is not possible when a parameter type is missing from the argument list." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-4018", + "properties": { + "category": "Minor Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S4019", + "shortDescription": { + "text": "Base class methods should not be hidden" + }, + "fullDescription": { + "text": "When a method in a derived class has:" + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-4019", + "properties": { + "category": "Critical Code Smell", + "executionTimeInSeconds": "0.024", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S4022", + "shortDescription": { + "text": "Enumerations should have \"Int32\" storage" + }, + "fullDescription": { + "text": "By default the storage type of an enum is Int32. In most cases it is not necessary to change this. In particular you will not achieve any performance gain by using a smaller data type (e.g. Byte) and may limit future uses." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-4022", + "properties": { + "category": "Minor Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S4023", + "shortDescription": { + "text": "Interfaces should not be empty" + }, + "fullDescription": { + "text": "Empty interfaces should be avoided as they do not provide any functional requirements for implementing classes." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-4023", + "properties": { + "category": "Minor Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope" + ] + } + }, + { + "id": "S4025", + "shortDescription": { + "text": "Child class fields should not differ from parent class fields only by capitalization" + }, + "fullDescription": { + "text": "Having a field in a child class with a name that differs from a parent class' field only by capitalization is sure to cause confusion. Such child class fields should be renamed." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-4025", + "properties": { + "category": "Critical Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S4026", + "shortDescription": { + "text": "Assemblies should be marked with \"NeutralResourcesLanguageAttribute\"" + }, + "fullDescription": { + "text": "It is important to inform the ResourceManager of the language used to display the resources of the neutral culture for an assembly. This improves lookup performance for the first resource loaded." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-4026", + "properties": { + "category": "Minor Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S4027", + "shortDescription": { + "text": "Exceptions should provide standard constructors" + }, + "fullDescription": { + "text": "Exceptions types should provide the following constructors:" + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-4027", + "properties": { + "category": "Minor Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S4035", + "shortDescription": { + "text": "Classes implementing \"IEquatable\" should be sealed" + }, + "fullDescription": { + "text": "When a class implements the IEquatable interface, it enters a contract that, in effect, states \"I know how to compare two instances of type T or any type derived from T for equality.\". However if that class is derived, it is very unlikely that the base class will know how to make a meaningful comparison. Therefore that implicit contract is now broken." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-4035", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "0.013", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S4036", + "shortDescription": { + "text": "Searching OS commands in PATH is security-sensitive" + }, + "fullDescription": { + "text": "When executing an OS command and unless you specify the full path to the executable, then the locations in your application’s PATH environment variable will be searched for the executable. That search could leave an opening for an attacker if one of the elements in PATH is a directory under his control." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-4036", + "properties": { + "category": "Minor Security Hotspot", + "executionTimeInSeconds": "0.002", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S4039", + "shortDescription": { + "text": "Interface methods should be callable by derived types" + }, + "fullDescription": { + "text": "When a base type explicitly implements a public interface method, property or event, that member is only accessible in derived types through a reference to the current instance (namely this). If the derived type explicitly overrides that interface member, the base implementation becomes inaccessible." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-4039", + "properties": { + "category": "Critical Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope" + ] + } + }, + { + "id": "S4040", + "shortDescription": { + "text": "Strings should be normalized to uppercase" + }, + "fullDescription": { + "text": "Certain characters, once normalized to lowercase, cannot make a round trip. That is, they can not be converted from one locale to another and then accurately restored to their original characters." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-4040", + "properties": { + "category": "Minor Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S4041", + "shortDescription": { + "text": "Type names should not match namespaces" + }, + "fullDescription": { + "text": "When a type name matches the name of a publicly defined namespace, for instance one in the .NET framework class library, it leads to confusion and makes the library that much harder to use." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-4041", + "properties": { + "category": "Minor Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S4047", + "shortDescription": { + "text": "Generics should be used when appropriate" + }, + "fullDescription": { + "text": "When a reference parameter (keyword ref) is used, the passed argument type must exactly match the reference parameter type. This means that to be able to pass a derived type, it must be cast and assigned to a variable of the proper type. Use of generic methods eliminates that cumbersome down casting and should therefore be preferred." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-4047", + "properties": { + "category": "Minor Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S4049", + "shortDescription": { + "text": "Properties should be preferred" + }, + "fullDescription": { + "text": "Properties are accessed like fields which makes them easier to use." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-4049", + "properties": { + "category": "Minor Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope" + ] + } + }, + { + "id": "S4050", + "shortDescription": { + "text": "Operators should be overloaded consistently" + }, + "fullDescription": { + "text": "When overloading some arithmetic operator overloads, it is very important to make sure that all related operators and methods are consistent in their implementation." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-4050", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "0.018", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S4052", + "shortDescription": { + "text": "Types should not extend outdated base types" + }, + "fullDescription": { + "text": "With the advent of .NET Framework 2.0, certain practices and types have become obsolete." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-4052", + "properties": { + "category": "Minor Code Smell", + "executionTimeInSeconds": "0.007", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S4055", + "shortDescription": { + "text": "Literals should not be passed as localized parameters" + }, + "fullDescription": { + "text": "String literals embedded in the source code will not be localized properly." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-4055", + "properties": { + "category": "Major Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope" + ] + } + }, + { + "id": "S4056", + "shortDescription": { + "text": "Overloads with a \"CultureInfo\" or an \"IFormatProvider\" parameter should be used" + }, + "fullDescription": { + "text": "When a System.Globalization.CultureInfo or IFormatProvider object is not supplied, the default value that is supplied by the overloaded member might not have the effect that you want in all locales." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-4056", + "properties": { + "category": "Minor Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S4057", + "shortDescription": { + "text": "Locales should be set for data types" + }, + "fullDescription": { + "text": "When you create a DataTable or DataSet, you should set the locale explicitly. By default, the locale for these types is the current culture. For data that is stored in a database or file and is shared globally, the locale should ordinarily be set to the invariant culture (CultureInfo.InvariantCulture)." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-4057", + "properties": { + "category": "Major Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S4058", + "shortDescription": { + "text": "Overloads with a \"StringComparison\" parameter should be used" + }, + "fullDescription": { + "text": "Many string operations, the Compare and Equals methods in particular, provide an overload that accepts a StringComparison enumeration value as a parameter. Calling these overloads and explicitly providing this parameter makes your code clearer and easier to maintain." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-4058", + "properties": { + "category": "Minor Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S4059", + "shortDescription": { + "text": "Property names should not match get methods" + }, + "fullDescription": { + "text": "Properties and Get method should have names that makes them clearly distinguishable." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-4059", + "properties": { + "category": "Major Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S4060", + "shortDescription": { + "text": "Non-abstract attributes should be sealed" + }, + "fullDescription": { + "text": "The .NET framework class library provides methods for retrieving custom attributes. Sealing the attribute eliminates the search through the inheritance hierarchy, and can improve performance." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-4060", + "properties": { + "category": "Minor Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope" + ] + } + }, + { + "id": "S4061", + "shortDescription": { + "text": "\"params\" should be used instead of \"varargs\"" + }, + "fullDescription": { + "text": "A method using the VarArgs calling convention is not Common Language Specification (CLS) compliant and might not be accessible across programming languages, while the params keyword works the same way and is CLS compliant." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-4061", + "properties": { + "category": "Minor Code Smell", + "executionTimeInSeconds": "0.008", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S4069", + "shortDescription": { + "text": "Operator overloads should have named alternatives" + }, + "fullDescription": { + "text": "Operator overloading is convenient but unfortunately not portable across languages. To be able to access the same functionality from another language you need to provide an alternate named method following the convention:" + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-4069", + "properties": { + "category": "Minor Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope" + ] + } + }, + { + "id": "S4070", + "shortDescription": { + "text": "Non-flags enums should not be marked with \"FlagsAttribute\"" + }, + "fullDescription": { + "text": "This rule raises an issue when an externally visible enumeration is marked with FlagsAttribute and one, or more, of its values is not a power of 2 or a combination of the other defined values." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-4070", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "0.007", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S4136", + "shortDescription": { + "text": "Method overloads should be grouped together" + }, + "fullDescription": { + "text": "For clarity, all overloads of the same method should be grouped together. That lets both users and maintainers quickly understand all the current available options." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-4136", + "properties": { + "category": "Minor Code Smell", + "executionTimeInSeconds": "0.033", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S4143", + "shortDescription": { + "text": "Collection elements should not be replaced unconditionally" + }, + "fullDescription": { + "text": "Storing a value inside a collection at a given key or index and then unconditionally overwriting it without reading the initial value is a case of a \"dead store\"." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-4143", + "properties": { + "category": "Major Bug", + "executionTimeInSeconds": "0.007", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S4144", + "shortDescription": { + "text": "Methods should not have identical implementations" + }, + "fullDescription": { + "text": "Two methods having the same implementation are suspicious. It might be that something else was intended. Or the duplication is intentional, which becomes a maintenance burden." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-4144", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "0.059", + "executionTimeInPercentage": "1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S4159", + "shortDescription": { + "text": "Classes should implement their \"ExportAttribute\" interfaces" + }, + "fullDescription": { + "text": "The Attributed Programming Model, also known as Attribute-oriented programming (@OP), is a programming model used to embed attributes within codes." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-4159", + "properties": { + "category": "Blocker Bug", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S4200", + "shortDescription": { + "text": "Native methods should be wrapped" + }, + "fullDescription": { + "text": "Native methods are functions that reside in libraries outside the .NET runtime. Calling them is helpful for interoperability with applications and libraries written in other programming languages, mainly when performing platform-specific operations. However, doing so comes with additional risks since it means stepping out of the memory-safety model of the runtime. It is therefore highly recommended to take extra steps, like input validation, when invoking native methods. Making the native method private and providing a wrapper that performs these additional steps is the best way to do so." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-4200", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "0.025", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S4201", + "shortDescription": { + "text": "Null checks should not be combined with \"is\" operator checks" + }, + "fullDescription": { + "text": "There’s no need to null test in conjunction with an is test. null is not an instance of anything, so a null check is redundant." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-4201", + "properties": { + "category": "Minor Code Smell", + "executionTimeInSeconds": "0.009", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S4210", + "shortDescription": { + "text": "Windows Forms entry points should be marked with STAThread" + }, + "fullDescription": { + "text": "When an assembly uses Windows Forms (classes and interfaces from the System.Windows.Forms namespace) its entry point should be marked with the STAThreadAttribute to indicate that the threading model should be \"Single-Threaded Apartment\" (STA) which is the only one supported by Windows Forms." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-4210", + "properties": { + "category": "Major Bug", + "executionTimeInSeconds": "0.006", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S4211", + "shortDescription": { + "text": "Members should not have conflicting transparency annotations" + }, + "fullDescription": { + "text": "Transparency attributes in the .NET Framework, designed to protect security-critical operations, can lead to ambiguities and vulnerabilities when declared at different levels such as both for the class and a method." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-4211", + "properties": { + "category": "Major Vulnerability", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S4212", + "shortDescription": { + "text": "Serialization constructors should be secured" + }, + "fullDescription": { + "text": "This rule is deprecated, and will eventually be removed." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-4212", + "properties": { + "category": "Major Vulnerability", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope" + ] + } + }, + { + "id": "S4214", + "shortDescription": { + "text": "\"P/Invoke\" methods should not be visible" + }, + "fullDescription": { + "text": "This rule is deprecated; use {rule:csharpsquid:S4200} instead." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-4214", + "properties": { + "category": "Major Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope" + ] + } + }, + { + "id": "S4220", + "shortDescription": { + "text": "Events should have proper arguments" + }, + "fullDescription": { + "text": "When raising an event, two arguments are expected by the EventHandler delegate: Sender and event-data. There are three guidelines regarding these parameters:" + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-4220", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "0.003", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S4225", + "shortDescription": { + "text": "Extension methods should not extend \"object\"" + }, + "fullDescription": { + "text": "Creating an extension method that extends object is not recommended because it makes the method available on every type. Extensions should be applied at the most specialized level possible, and that is very unlikely to be object." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-4225", + "properties": { + "category": "Minor Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S4226", + "shortDescription": { + "text": "Extensions should be in separate namespaces" + }, + "fullDescription": { + "text": "It makes little sense to create an extension method when it is possible to just add that method to the class itself." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-4226", + "properties": { + "category": "Minor Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S4260", + "shortDescription": { + "text": "\"ConstructorArgument\" parameters should exist in constructors" + }, + "fullDescription": { + "text": "When creating a custom Markup Extension that accepts parameters in WPF, the ConstructorArgument markup must be used to identify the discrete properties that match these parameters. However since this is done via a string, the compiler won’t give you any warning in case there are typos." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-4260", + "properties": { + "category": "Major Bug", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S4261", + "shortDescription": { + "text": "Methods should be named according to their synchronicities" + }, + "fullDescription": { + "text": "According to the Task-based Asynchronous Pattern (TAP), methods returning either a System.Threading.Tasks.Task or a System.Threading.Tasks.Task are considered \"asynchronous\". Such methods should use the Async suffix. Conversely methods which do not return such Tasks should not have an \"Async\" suffix in their names." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-4261", + "properties": { + "category": "Minor Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S4275", + "shortDescription": { + "text": "Getters and setters should access the expected fields" + }, + "fullDescription": { + "text": "Properties provide a way to enforce encapsulation by providing accessors that give controlled access to private fields. However, in classes with multiple fields, it is not unusual that copy-and-paste is used to quickly create the needed properties, which can result in the wrong field being accessed by a getter or setter." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-4275", + "properties": { + "category": "Critical Bug", + "executionTimeInSeconds": "0.091", + "executionTimeInPercentage": "1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S4277", + "shortDescription": { + "text": "\"Shared\" parts should not be created with \"new\"" + }, + "fullDescription": { + "text": "Marking a class with PartCreationPolicy(CreationPolicy.Shared), which is part of Managed Extensibility Framework (MEF), means that a single, shared instance of the exported object will be created. Therefore it doesn’t make sense to create new instances using the constructor and it will most likely result in unexpected behaviours." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-4277", + "properties": { + "category": "Critical Bug", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S4423", + "shortDescription": { + "text": "Weak SSL/TLS protocols should not be used" + }, + "fullDescription": { + "text": "This vulnerability exposes encrypted data to a number of attacks whose goal is to recover the plaintext." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-4423", + "properties": { + "category": "Critical Vulnerability", + "executionTimeInSeconds": "0.010", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S4426", + "shortDescription": { + "text": "Cryptographic keys should be robust" + }, + "fullDescription": { + "text": "This vulnerability exposes encrypted data to attacks whose goal is to recover the plaintext." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-4426", + "properties": { + "category": "Critical Vulnerability", + "executionTimeInSeconds": "0.015", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S4428", + "shortDescription": { + "text": "\"PartCreationPolicyAttribute\" should be used with \"ExportAttribute\"" + }, + "fullDescription": { + "text": "To customize the default behavior for an export in the Managed Extensibility Framework (MEF), applying the PartCreationPolicyAttribute is necessary. For the PartCreationPolicyAttribute to be meaningful in the context of an export, the class must also be annotated with the ExportAttribute." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-4428", + "properties": { + "category": "Major Bug", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S4433", + "shortDescription": { + "text": "LDAP connections should be authenticated" + }, + "fullDescription": { + "text": "Lightweight Directory Access Protocol (LDAP) servers provide two main authentication methods: the SASL and Simple ones. The Simple Authentication method also breaks down into three different mechanisms:" + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-4433", + "properties": { + "category": "Critical Vulnerability", + "executionTimeInSeconds": "0.011", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S4456", + "shortDescription": { + "text": "Parameter validation in yielding methods should be wrapped" + }, + "fullDescription": { + "text": "Because of the way yield methods are rewritten by the compiler (they become lazily evaluated state machines) any exceptions thrown during the parameters check will happen only when the collection is iterated over. That could happen far away from the source of the buggy code." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-4456", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "0.004", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S4457", + "shortDescription": { + "text": "Parameter validation in \"async\"/\"await\" methods should be wrapped" + }, + "fullDescription": { + "text": "Because of the way async/await methods are rewritten by the compiler, any exceptions thrown during the parameters check will happen only when the task is observed. That could happen far away from the source of the buggy code or never happen for fire-and-forget tasks." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-4457", + "properties": { + "category": "Major Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S4462", + "shortDescription": { + "text": "Calls to \"async\" methods should not be blocking" + }, + "fullDescription": { + "text": "Making blocking calls to async methods transforms code that was intended to be asynchronous into a blocking operation. Doing so can cause deadlocks and unexpected blocking of context threads." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-4462", + "properties": { + "category": "Blocker Code Smell", + "executionTimeInSeconds": "0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope" + ] + } + }, + { + "id": "S4487", + "shortDescription": { + "text": "Unread \"private\" fields should be removed" + }, + "fullDescription": { + "text": "Private fields which are written but never read are a case of \"dead store\". Changing the value of such a field is useless and most probably indicates an error in the code." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-4487", + "properties": { + "category": "Critical Code Smell", + "executionTimeInSeconds": "0.190", + "executionTimeInPercentage": "3", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S4502", + "shortDescription": { + "text": "Disabling CSRF protections is security-sensitive" + }, + "fullDescription": { + "text": "A cross-site request forgery (CSRF) attack occurs when a trusted user of a web application can be forced, by an attacker, to perform sensitive actions that he didn’t intend, such as updating his profile or sending a message, more generally anything that can change the state of the application." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-4502", + "properties": { + "category": "Critical Security Hotspot", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S4507", + "shortDescription": { + "text": "Delivering code in production with debug features activated is security-sensitive" + }, + "fullDescription": { + "text": "Development tools and frameworks usually have options to make debugging easier for developers. Although these features are useful during development, they should never be enabled for applications deployed in production. Debug instructions or error messages can leak detailed information about the system, like the application’s path or file names." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-4507", + "properties": { + "category": "Minor Security Hotspot", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S4524", + "shortDescription": { + "text": "\"default\" clauses should be first or last" + }, + "fullDescription": { + "text": "The switch statement is a conditional statement that executes a sequence of instructions based on patterns matching the provided value." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-4524", + "properties": { + "category": "Critical Code Smell", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S4545", + "shortDescription": { + "text": "\"DebuggerDisplayAttribute\" strings should reference existing members" + }, + "fullDescription": { + "text": "The DebuggerDisplayAttribute is used to determine how an object is displayed in the debugger window." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-4545", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S4581", + "shortDescription": { + "text": "\"new Guid()\" should not be used" + }, + "fullDescription": { + "text": "When the syntax new Guid() (i.e. parameterless instantiation) is used, it must be that one of three things is wanted:" + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-4581", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S4583", + "shortDescription": { + "text": "Calls to delegate's method \"BeginInvoke\" should be paired with calls to \"EndInvoke\"" + }, + "fullDescription": { + "text": "When calling the BeginInvoke method of a delegate, resources are allocated that are only freed up when EndInvoke is called. Failing to pair BeginInvoke with EndInvoke can lead to resource leaks and incomplete asynchronous calls." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-4583", + "properties": { + "category": "Critical Bug", + "executionTimeInSeconds": "0.038", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S4586", + "shortDescription": { + "text": "Non-async \"Task/Task\" methods should not return null" + }, + "fullDescription": { + "text": "Returning null from a non-async Task/Task method will cause a NullReferenceException at runtime if the method is awaited. This problem can be avoided by returning Task.CompletedTask or Task.FromResult(null) respectively." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-4586", + "properties": { + "category": "Critical Bug", + "executionTimeInSeconds": "0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S4635", + "shortDescription": { + "text": "Start index should be used instead of calling Substring" + }, + "fullDescription": { + "text": "It is important to be careful when searching for characters within a substring. Let’s consider the following example:" + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-4635", + "properties": { + "category": "Critical Code Smell", + "executionTimeInSeconds": "0.008", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S4663", + "shortDescription": { + "text": "Comments should not be empty" + }, + "fullDescription": { + "text": "Empty comments, as shown in the example, hurt readability and might indicate an oversight." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-4663", + "properties": { + "category": "Minor Code Smell", + "executionTimeInSeconds": "0.012", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S4790", + "shortDescription": { + "text": "Using weak hashing algorithms is security-sensitive" + }, + "fullDescription": { + "text": "Cryptographic hash algorithms such as MD2, MD4, MD5, MD6, HAVAL-128, HMAC-MD5, DSA (which uses SHA-1), RIPEMD, RIPEMD-128, RIPEMD-160, HMACRIPEMD160 and SHA-1 are no longer considered secure, because it is possible to have collisions (little computational effort is enough to find two or more different inputs that produce the same hash)." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-4790", + "properties": { + "category": "Critical Security Hotspot", + "executionTimeInSeconds": "0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S4792", + "shortDescription": { + "text": "Configuring loggers is security-sensitive" + }, + "fullDescription": { + "text": "This rule is deprecated, and will eventually be removed." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-4792", + "properties": { + "category": "Critical Security Hotspot", + "executionTimeInSeconds": "0.003", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope" + ] + } + }, + { + "id": "S4830", + "shortDescription": { + "text": "Server certificates should be verified during SSL/TLS connections" + }, + "fullDescription": { + "text": "This vulnerability makes it possible that an encrypted communication is intercepted." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-4830", + "properties": { + "category": "Critical Vulnerability", + "executionTimeInSeconds": "0.005", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S5034", + "shortDescription": { + "text": "\"ValueTask\" should be consumed correctly" + }, + "fullDescription": { + "text": "ValueTask provides a value type that wraps a Task and the corresponding TResult. It was introduced in .NET Core 2.0 to optimize memory allocation when functions return their results synchronously." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-5034", + "properties": { + "category": "Critical Code Smell", + "executionTimeInSeconds": "0.013", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S5042", + "shortDescription": { + "text": "Expanding archive files without controlling resource consumption is security-sensitive" + }, + "fullDescription": { + "text": "Successful Zip Bomb attacks occur when an application expands untrusted archive files without controlling the size of the expanded data, which can lead to denial of service. A Zip bomb is usually a malicious archive file of a few kilobytes of compressed data but turned into gigabytes of uncompressed data. To achieve this extreme compression ratio, attackers will compress irrelevant data (eg: a long string of repeated bytes)." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-5042", + "properties": { + "category": "Critical Security Hotspot", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S5122", + "shortDescription": { + "text": "Having a permissive Cross-Origin Resource Sharing policy is security-sensitive" + }, + "fullDescription": { + "text": "Having a permissive Cross-Origin Resource Sharing policy is security-sensitive. It has led in the past to the following vulnerabilities:" + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-5122", + "properties": { + "category": "Minor Security Hotspot", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S5332", + "shortDescription": { + "text": "Using clear-text protocols is security-sensitive" + }, + "fullDescription": { + "text": "Clear-text protocols such as ftp, telnet, or http lack encryption of transported data, as well as the capability to build an authenticated connection. It means that an attacker able to sniff traffic from the network can read, modify, or corrupt the transported content. These protocols are not secure as they expose applications to an extensive range of risks:" + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-5332", + "properties": { + "category": "Critical Security Hotspot", + "executionTimeInSeconds": "0.002", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S5344", + "shortDescription": { + "text": "Passwords should not be stored in plaintext or with a fast hashing algorithm" + }, + "fullDescription": { + "text": "The improper storage of passwords poses a significant security risk to software applications. This vulnerability arises when passwords are stored in plaintext or with a fast hashing algorithm. To exploit this vulnerability, an attacker typically requires access to the stored passwords." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-5344", + "properties": { + "category": "Critical Vulnerability", + "executionTimeInSeconds": "0.014", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S5443", + "shortDescription": { + "text": "Using publicly writable directories is security-sensitive" + }, + "fullDescription": { + "text": "Operating systems have global directories where any user has write access. Those folders are mostly used as temporary storage areas like /tmp in Linux based systems. An application manipulating files from these folders is exposed to race conditions on filenames: a malicious user can try to create a file with a predictable name before the application does. A successful attack can result in other files being accessed, modified, corrupted or deleted. This risk is even higher if the application runs with elevated permissions." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-5443", + "properties": { + "category": "Critical Security Hotspot", + "executionTimeInSeconds": "0.006", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S5445", + "shortDescription": { + "text": "Insecure temporary file creation methods should not be used" + }, + "fullDescription": { + "text": "Temporary files are considered insecurely created when the file existence check is performed separately from the actual file creation. Such a situation can occur when creating temporary files using normal file handling functions or when using dedicated temporary file handling functions that are not atomic." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-5445", + "properties": { + "category": "Critical Vulnerability", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S5542", + "shortDescription": { + "text": "Encryption algorithms should be used with secure mode and padding scheme" + }, + "fullDescription": { + "text": "This vulnerability exposes encrypted data to a number of attacks whose goal is to recover the plaintext." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-5542", + "properties": { + "category": "Critical Vulnerability", + "executionTimeInSeconds": "0.008", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S5547", + "shortDescription": { + "text": "Cipher algorithms should be robust" + }, + "fullDescription": { + "text": "This vulnerability makes it possible that the cleartext of the encrypted message might be recoverable without prior knowledge of the key." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-5547", + "properties": { + "category": "Critical Vulnerability", + "executionTimeInSeconds": "0.040", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S5659", + "shortDescription": { + "text": "JWT should be signed and verified with strong cipher algorithms" + }, + "fullDescription": { + "text": "This vulnerability allows forging of JSON Web Tokens to impersonate other users." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-5659", + "properties": { + "category": "Critical Vulnerability", + "executionTimeInSeconds": "0.002", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S5693", + "shortDescription": { + "text": "Allowing requests with excessive content length is security-sensitive" + }, + "fullDescription": { + "text": "Rejecting requests with significant content length is a good practice to control the network traffic intensity and thus resource consumption in order to prevent DoS attacks." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-5693", + "properties": { + "category": "Major Security Hotspot", + "executionTimeInSeconds": "0.010", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S5753", + "shortDescription": { + "text": "Disabling ASP.NET \"Request Validation\" feature is security-sensitive" + }, + "fullDescription": { + "text": "ASP.NET 1.1+ comes with a feature called Request Validation, preventing the server to accept content containing un-encoded HTML. This feature comes as a first protection layer against Cross-Site Scripting (XSS) attacks and act as a simple Web Application Firewall (WAF) rejecting requests potentially containing malicious content." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-5753", + "properties": { + "category": "Major Security Hotspot", + "executionTimeInSeconds": "0.006", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S5766", + "shortDescription": { + "text": "Deserializing objects without performing data validation is security-sensitive" + }, + "fullDescription": { + "text": "Deserialization process extracts data from the serialized representation of an object and reconstruct it directly, without calling constructors. Thus, data validation implemented in constructors can be bypassed if serialized objects are controlled by an attacker." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-5766", + "properties": { + "category": "Major Security Hotspot", + "executionTimeInSeconds": "0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S5856", + "shortDescription": { + "text": "Regular expressions should be syntactically valid" + }, + "fullDescription": { + "text": "Regular expressions have their own syntax that is understood by regular expression engines. Those engines will throw an exception at runtime if they are given a regular expression that does not conform to that syntax." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-5856", + "properties": { + "category": "Critical Bug", + "executionTimeInSeconds": "0.010", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S6354", + "shortDescription": { + "text": "Use a testable date/time provider" + }, + "fullDescription": { + "text": "One of the principles of a unit test is that it must have full control of the system under test. This is problematic when production code includes calls to static methods, which cannot be changed or controlled. Date/time functions are usually provided by system libraries as static methods." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-6354", + "properties": { + "category": "Major Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope" + ] + } + }, + { + "id": "S6377", + "shortDescription": { + "text": "XML signatures should be validated securely" + }, + "fullDescription": { + "text": "XML signatures are a method used to ensure the integrity and authenticity of XML documents. However, if XML signatures are not validated securely, it can lead to potential vulnerabilities." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-6377", + "properties": { + "category": "Major Vulnerability", + "executionTimeInSeconds": "0.003", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S6418", + "shortDescription": { + "text": "Hard-coded secrets are security-sensitive" + }, + "fullDescription": { + "text": "Because it is easy to extract strings from an application source code or binary, secrets should not be hard-coded. This is particularly true for applications that are distributed or that are open-source." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-6418", + "properties": { + "category": "Blocker Security Hotspot", + "executionTimeInSeconds": "0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S6419", + "shortDescription": { + "text": "Azure Functions should be stateless" + }, + "fullDescription": { + "text": "An Azure Function should be stateless as there’s no control over where and when function instances are provisioned and de-provisioned. Managing and storing data/state between requests can lead to inconsistencies. If, for any reason, you need to have a stateful function, consider using the Durable Functions extension of Azure Functions." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-6419", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "0.007", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S6420", + "shortDescription": { + "text": "Client instances should not be recreated on each Azure Function invocation" + }, + "fullDescription": { + "text": "To avoid holding more connections than necessary and to avoid potentially exhausting the number of available sockets when using HttpClient, DocumentClient, QueueClient, ConnectionMultiplexer or Azure Storage clients, consider:" + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-6420", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S6421", + "shortDescription": { + "text": "Azure Functions should use Structured Error Handling" + }, + "fullDescription": { + "text": "The top-most level of an Azure Function code should include a try/catch block to capture and log all errors so you can monitor the health of the application effectively. In case a retry policy has been defined for your Azure Function, you should rethrow any errors that should result in a retry." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-6421", + "properties": { + "category": "Major Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope" + ] + } + }, + { + "id": "S6422", + "shortDescription": { + "text": "Calls to \"async\" methods should not be blocking in Azure Functions" + }, + "fullDescription": { + "text": "Making blocking calls to async methods transforms the code into a synchronous operation. Doing so inside an Azure Function can lead to thread pool exhaustion." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-6422", + "properties": { + "category": "Blocker Code Smell", + "executionTimeInSeconds": "0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S6423", + "shortDescription": { + "text": "Azure Functions should log all failures" + }, + "fullDescription": { + "text": "Capturing and logging errors is critical to monitoring the health of your Azure Functions application." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-6423", + "properties": { + "category": "Major Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope" + ] + } + }, + { + "id": "S6424", + "shortDescription": { + "text": "Interfaces for durable entities should satisfy the restrictions" + }, + "fullDescription": { + "text": "The recommended way to access Azure Durable Entities is through generated proxy objects with the help of interfaces." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-6424", + "properties": { + "category": "Blocker Code Smell", + "executionTimeInSeconds": "0.003", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S6444", + "shortDescription": { + "text": "Not specifying a timeout for regular expressions is security-sensitive" + }, + "fullDescription": { + "text": "Not specifying a timeout for regular expressions can lead to a Denial-of-Service attack. Pass a timeout when using System.Text.RegularExpressions to process untrusted input because a malicious user might craft a value for which the evaluation lasts excessively long." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-6444", + "properties": { + "category": "Major Security Hotspot", + "executionTimeInSeconds": "0.002", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S6507", + "shortDescription": { + "text": "Blocks should not be synchronized on local variables" + }, + "fullDescription": { + "text": "Locking on a local variable can undermine synchronization because two different threads running the same method in parallel will potentially lock on different instances of the same object, allowing them to access the synchronized block at the same time." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-6507", + "properties": { + "category": "Major Bug", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S6513", + "shortDescription": { + "text": "\"ExcludeFromCodeCoverage\" attributes should include a justification" + }, + "fullDescription": { + "text": "The ExcludeFromCodeCoverageAttribute is used to exclude portions of code from code coverage reporting. It is a bad practice to retain code that is not covered by unit tests. In .Net 5, the Justification property was added to the ExcludeFromCodeCoverageAttribute as an opportunity to document the rationale for the exclusion. This rule raises an issue when no such justification is given." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-6513", + "properties": { + "category": "Minor Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope" + ] + } + }, + { + "id": "S6561", + "shortDescription": { + "text": "Avoid using \"DateTime.Now\" for benchmarking or timing operations" + }, + "fullDescription": { + "text": "The rule targets the use of DateTime.Now call followed by some arithmetic operation." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-6561", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "0.009", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S6562", + "shortDescription": { + "text": "Always set the \"DateTimeKind\" when creating new \"DateTime\" instances" + }, + "fullDescription": { + "text": "Not knowing the Kind of the DateTime object that an application is using can lead to misunderstandings when displaying or comparing them. Explicitly setting the Kind property helps the application to stay consistent, and its maintainers understand what kind of date is being managed. To achieve this, when instantiating a new DateTime object you should always use a constructor overload that allows you to define the Kind property." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-6562", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S6563", + "shortDescription": { + "text": "Use UTC when recording DateTime instants" + }, + "fullDescription": { + "text": "You should avoid recording time instants with the use of property DateTime.Now. The property DateTime.Now returns the current date and time expressed in the machine’s local time without containing any timezone-related information (for example, the offset from Coordinated Universal Time). Not having this information means that if you need to display this DateTime object or use it for computations in another machine placed in a different time zone, you won’t be able to reconstruct it in the second machine’s local time without knowing the origin’s offset. This will likely lead to confusion and potential bugs." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-6563", + "properties": { + "category": "Major Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S6566", + "shortDescription": { + "text": "Use \"DateTimeOffset\" instead of \"DateTime\"" + }, + "fullDescription": { + "text": "This rule recommends using DateTimeOffset instead of DateTime for projects targeting .NET Framework 2.0 or later." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-6566", + "properties": { + "category": "Major Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S6575", + "shortDescription": { + "text": "Use \"TimeZoneInfo.FindSystemTimeZoneById\" without converting the timezones with \"TimezoneConverter\"" + }, + "fullDescription": { + "text": "Since .NET 6 you don’t have to use the TimeZoneConverter library to manually do the conversion between IANA and Windows timezones. The .NET 6.0 introduced new Time Zone enhancements, one being the TimeZoneInfo.FindSystemTimeZoneById(string timezone) method now accepts as input both IANA and Windows time zone IDs on any operating system with installed time zone data. TimeZoneInfo.FindSystemTimeZoneById will automatically convert its input from IANA to Windows and vice versa if the requested time zone is not found on the system." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-6575", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S6580", + "shortDescription": { + "text": "Use a format provider when parsing date and time" + }, + "fullDescription": { + "text": "When converting a string representation of a date and time to a DateTime object or any other temporal type with one of the available system parsing methods, you should always provide an IFormatProvider parameter." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-6580", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "0.021", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S6585", + "shortDescription": { + "text": "Don't hardcode the format when turning dates and times to strings" + }, + "fullDescription": { + "text": "Hardcoding the date and time format strings can lead to formats that consumers misunderstand. Also, if the same format is meant to be used in multiple places, it is easier to make a mistake when it’s hardcoded instead of using a format provided by an IFormatProvider or using one of the standard format strings." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-6585", + "properties": { + "category": "Minor Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S6588", + "shortDescription": { + "text": "Use the \"UnixEpoch\" field instead of creating \"DateTime\" instances that point to the beginning of the Unix epoch" + }, + "fullDescription": { + "text": "With .NET Core the UnixEpoch field was introduced to DateTime and DateTimeOffset types. Using this field clearly states that the intention is to use the beginning of the Unix epoch." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-6588", + "properties": { + "category": "Minor Code Smell", + "executionTimeInSeconds": "0.004", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S6602", + "shortDescription": { + "text": "\"Find\" method should be used instead of the \"FirstOrDefault\" extension" + }, + "fullDescription": { + "text": "Both the List.Find method and the Enumerable.FirstOrDefault method can be used to locate the first element that meets a specified condition within a collection. However, for List objects, List.Find may offer superior performance compared to Enumerable.FirstOrDefault. While the performance difference might be negligible for small collections, it can become significant for larger collections. This observation also holds true for ImmutableList and arrays." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-6602", + "properties": { + "category": "Minor Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S6603", + "shortDescription": { + "text": "The collection-specific \"TrueForAll\" method should be used instead of the \"All\" extension" + }, + "fullDescription": { + "text": "Both the List.TrueForAll method and the IEnumerable.All method can be used to check if all list elements satisfy a given condition in a collection. However, List.TrueForAll can be faster than IEnumerable.All for List objects. The performance difference may be minor for small collections, but for large collections, it can be noticeable." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-6603", + "properties": { + "category": "Minor Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S6605", + "shortDescription": { + "text": "Collection-specific \"Exists\" method should be used instead of the \"Any\" extension" + }, + "fullDescription": { + "text": "Both the List.Exists method and IEnumerable.Any method can be used to find the first element that satisfies a predicate in a collection. However, List.Exists can be faster than IEnumerable.Any for List objects, as well as requires significantly less memory. For small collections, the performance difference may be negligible, but for large collections, it can be noticeable. The same applies to ImmutableList and arrays too." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-6605", + "properties": { + "category": "Minor Code Smell", + "executionTimeInSeconds": "0.002", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S6607", + "shortDescription": { + "text": "The collection should be filtered before sorting by using \"Where\" before \"OrderBy\"" + }, + "fullDescription": { + "text": "When working with LINQ in C#, it is recommended to pay attention to the order in which methods are chained, especially when using Where and OrderBy methods. It is advised to call the Where method before OrderBy because Where filters the elements of the sequence based on a given condition and returns a new sequence containing only the elements that satisfy that condition. Calling OrderBy before Where, may end up sorting elements that will be later discarded, which can lead to inefficiency. Conversely, calling Where before OrderBy, will first filter the sequence to include only the elements of interest, and then sort them based on the specified order." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-6607", + "properties": { + "category": "Minor Code Smell", + "executionTimeInSeconds": "0.010", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S6608", + "shortDescription": { + "text": "Prefer indexing instead of \"Enumerable\" methods on types implementing \"IList\"" + }, + "fullDescription": { + "text": "Indexes in C# provide direct access to an element at a specific position within an array or collection. When compared to Enumerable methods, indexing can be more efficient for certain scenarios, such as iterating over a large collection, due to avoiding the overhead of checking the underlying collection type before accessing it." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-6608", + "properties": { + "category": "Minor Code Smell", + "executionTimeInSeconds": "0.008", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S6609", + "shortDescription": { + "text": "\"Min/Max\" properties of \"Set\" types should be used instead of the \"Enumerable\" extension methods" + }, + "fullDescription": { + "text": "Both the Enumerable.Max extension method and the SortedSet.Max property can be used to find the maximum value in a SortedSet. However, SortedSet.Max is much faster than Enumerable.Max. For small collections, the performance difference may be minor, but for large collections, it can be noticeable. The same applies for the Min property as well." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-6609", + "properties": { + "category": "Minor Code Smell", + "executionTimeInSeconds": "0.002", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S6610", + "shortDescription": { + "text": "\"StartsWith\" and \"EndsWith\" overloads that take a \"char\" should be used instead of the ones that take a \"string\"" + }, + "fullDescription": { + "text": "With string.StartsWith(char) and string.EndsWith(char), only the first character of the string is compared to the provided character, whereas the string versions of those methods have to do checks about the current StringComparison and CultureInfo. Thus, the char overloads are significantly faster for default comparison scenarios." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-6610", + "properties": { + "category": "Minor Code Smell", + "executionTimeInSeconds": "0.013", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S6612", + "shortDescription": { + "text": "The lambda parameter should be used instead of capturing arguments in \"ConcurrentDictionary\" methods" + }, + "fullDescription": { + "text": "When using the ConcurrentDictionary, there are many overloads of the GetOrAdd and AddOrUpdate methods that take both a TKey argument and a lambda that expects a TKey parameter. This means that the right side of the lambda can be written using either the lambda’s parameter or the method’s argument. However, using the method’s argument leads to the lambda capturing it, and the compiler will need to generate a class and instantiate it before the call. This means memory allocations, as well as more time spend during Garbage Collection." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-6612", + "properties": { + "category": "Minor Code Smell", + "executionTimeInSeconds": "0.020", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S6613", + "shortDescription": { + "text": "\"First\" and \"Last\" properties of \"LinkedList\" should be used instead of the \"First()\" and \"Last()\" extension methods" + }, + "fullDescription": { + "text": "Both the Enumerable.First extension method and the LinkedList.First property can be used to find the first value in a LinkedList. However, LinkedList.First is much faster than Enumerable.First. For small collections, the performance difference may be minor, but for large collections, it can be noticeable. The same applies for the Last property as well." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-6613", + "properties": { + "category": "Minor Code Smell", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S6617", + "shortDescription": { + "text": "\"Contains\" should be used instead of \"Any\" for simple equality checks" + }, + "fullDescription": { + "text": "When testing if a collection contains a specific item by simple equality, both ICollection.Contains(T item) and IEnumerable.Any(x ⇒ x == item) can be used. However, Any searches the data structure in a linear manner using a foreach loop, whereas Contains is considerably faster in some collection types, because of the underlying implementation. More specifically:" + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-6617", + "properties": { + "category": "Minor Code Smell", + "executionTimeInSeconds": "0.002", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S6618", + "shortDescription": { + "text": "\"string.Create\" should be used instead of \"FormattableString\"" + }, + "fullDescription": { + "text": "In order to produce a formatted string, both string.Create and either FormattableString.Invariant or FormattableString.CurrentCulture can be used. However, string.Create rents array buffers from ArrayPool making it more performant, as well as preventing unnecessary allocations and future stress on the Garbage Collector." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-6618", + "properties": { + "category": "Minor Code Smell", + "executionTimeInSeconds": "0.008", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S6640", + "shortDescription": { + "text": "Using unsafe code blocks is security-sensitive" + }, + "fullDescription": { + "text": "Using unsafe code blocks can lead to unintended security or stability risks." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-6640", + "properties": { + "category": "Major Security Hotspot", + "executionTimeInSeconds": "0.015", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S6664", + "shortDescription": { + "text": "The code block contains too many logging calls" + }, + "fullDescription": { + "text": "A code block should not contain too many logging statements of a specific level." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-6664", + "properties": { + "category": "Minor Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S6667", + "shortDescription": { + "text": "Logging in a catch clause should pass the caught exception as a parameter." + }, + "fullDescription": { + "text": "This rule raises an issue on logging calls inside a catch clause that does not pass the raised Exception." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-6667", + "properties": { + "category": "Minor Code Smell", + "executionTimeInSeconds": "0.009", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S6668", + "shortDescription": { + "text": "Logging arguments should be passed to the correct parameter" + }, + "fullDescription": { + "text": "Most logging frameworks have methods that take a log level, an event ID or an exception as a separate input next to the log format and its arguments. There is a high chance that if the log level, the event ID or the exception are passed as the arguments to the message format, it was a mistake. This rule is going to raise in that scenario." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-6668", + "properties": { + "category": "Minor Code Smell", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S6669", + "shortDescription": { + "text": "Logger field or property name should comply with a naming convention" + }, + "fullDescription": { + "text": "Sharing some naming conventions is a key point to make it possible for a team to efficiently collaborate. This rule checks that the logger field or property name matches a provided regular expression." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-6669", + "properties": { + "category": "Minor Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S6670", + "shortDescription": { + "text": "\"Trace.Write\" and \"Trace.WriteLine\" should not be used" + }, + "fullDescription": { + "text": "Trace.Write and Trace.WriteLine methods are writing to the underlying output stream directly, bypassing the trace formatting and filtering performed by TraceListener.TraceEvent implementations. It is preferred to use Trace.TraceError, Trace.TraceWarning, and Trace.TraceInformation methods instead because they call the TraceEvent method which filters the trace output according to the TraceEventType (Error, Warning or Information) and enhance the output with additional information." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-6670", + "properties": { + "category": "Minor Code Smell", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S6672", + "shortDescription": { + "text": "Generic logger injection should match enclosing type" + }, + "fullDescription": { + "text": "In most logging frameworks, it’s good practice to set the logger name to match its enclosing type, as enforced by {rule:csharpsquid:S3416}." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-6672", + "properties": { + "category": "Minor Code Smell", + "executionTimeInSeconds": "0.008", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S6673", + "shortDescription": { + "text": "Log message template placeholders should be in the right order" + }, + "fullDescription": { + "text": "The positions of arguments in a logging call should match the positions of their message template placeholders." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-6673", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "0.065", + "executionTimeInPercentage": "1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S6674", + "shortDescription": { + "text": "Log message template should be syntactically correct" + }, + "fullDescription": { + "text": "A message template must conform to the specification. The rule raises an issue if the template string violates the template string grammar." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-6674", + "properties": { + "category": "Critical Bug", + "executionTimeInSeconds": "0.020", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S6675", + "shortDescription": { + "text": "\"Trace.WriteLineIf\" should not be used with \"TraceSwitch\" levels" + }, + "fullDescription": { + "text": "The Trace.WriteLineIf Method from the System.Diagnostic.Trace facility writes a trace if the condition passed as the first parameter is true." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-6675", + "properties": { + "category": "Minor Code Smell", + "executionTimeInSeconds": "0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S6677", + "shortDescription": { + "text": "Message template placeholders should be unique" + }, + "fullDescription": { + "text": "Named placeholders in message templates should be unique. The meaning of the named placeholders is to store the value of the provided argument under that name, enabling easier log querying. Since the named placeholder is used multiple times, it cannot store the different values uniquely with each name hence not serving its original purpose. There can be different behaviours when using the same named placeholder multiple times:" + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-6677", + "properties": { + "category": "Major Bug", + "executionTimeInSeconds": "0.065", + "executionTimeInPercentage": "1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S6678", + "shortDescription": { + "text": "Use PascalCase for named placeholders" + }, + "fullDescription": { + "text": "Within a message template each named placeholder should be in PascalCase." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-6678", + "properties": { + "category": "Minor Code Smell", + "executionTimeInSeconds": "0.065", + "executionTimeInPercentage": "1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S6797", + "shortDescription": { + "text": "Blazor query parameter type should be supported" + }, + "fullDescription": { + "text": "The SupplyParameterFromQuery attribute can be used to specify that a component parameter, of a routable component, comes from the query string." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-6797", + "properties": { + "category": "Major Bug", + "executionTimeInSeconds": "0.002", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S6798", + "shortDescription": { + "text": "[JSInvokable] attribute should only be used on public methods" + }, + "fullDescription": { + "text": "In Blazor, the [JSInvokable] attribute is used to annotate a method, enabling it to be invoked from JavaScript code. The prerequisite for this functionality is that the method must be declared as public. Otherwise, a runtime error will be triggered when an attempt is made to call the method from JavaScript." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-6798", + "properties": { + "category": "Major Bug", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S6800", + "shortDescription": { + "text": "Component parameter type should match the route parameter type constraint" + }, + "fullDescription": { + "text": "In Blazor, when a route parameter constraint is applied, the value is automatically cast to the corresponding component parameter type. If the constraint type does not match the component parameter type, it can lead to confusion and potential runtime errors due to unsuccessful casting. Therefore, it is crucial to ensure that the types of route parameters and component parameters match to prevent such issues and maintain code clarity." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-6800", + "properties": { + "category": "Major Bug", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S6802", + "shortDescription": { + "text": "Using lambda expressions in loops should be avoided in Blazor markup section" + }, + "fullDescription": { + "text": "In Blazor, using lambda expressions as event handlers when the UI elements are rendered in a loop can lead to negative user experiences and performance issues. This is particularly noticeable when rendering a large number of elements." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-6802", + "properties": { + "category": "Major Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S6803", + "shortDescription": { + "text": "Parameters with SupplyParameterFromQuery attribute should be used only in routable components" + }, + "fullDescription": { + "text": "This rule is deprecated, and will eventually be removed." + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-6803", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "0.002", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S6930", + "shortDescription": { + "text": "Backslash should be avoided in route templates" + }, + "fullDescription": { + "text": "Backslash characters (\\) should be avoided in route templates." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-6930", + "properties": { + "category": "Major Bug", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S6931", + "shortDescription": { + "text": "ASP.NET controller actions should not have a route template starting with \"/\"" + }, + "fullDescription": { + "text": "Route templates for ASP.NET controller actions, defined via a RouteAttribute or any derivation of HttpMethodAttribute, should not start with \"/\"." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-6931", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S6932", + "shortDescription": { + "text": "Use model binding instead of reading raw request data" + }, + "fullDescription": { + "text": "The HttpRequest class provides access to the raw request data through the QueryString, Headers, and Forms properties. However, whenever possible it is recommended to use model binding instead of directly accessing the input data." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-6932", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "0.002", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S6934", + "shortDescription": { + "text": "A Route attribute should be added to the controller when a route template is specified at the action level" + }, + "fullDescription": { + "text": "When a route template is defined through an attribute on an action method, conventional routing for that action is disabled. To maintain good practice, it’s recommended not to combine conventional and attribute-based routing within a single controller to avoid unpredicted behavior. As such, the controller should exclude itself from conventional routing by applying a [Route] attribute." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-6934", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S6960", + "shortDescription": { + "text": "Controllers should not have mixed responsibilities" + }, + "fullDescription": { + "text": "ASP.NET controllers should not have mixed responsibilities. Following the Single Responsibility Principle (SRP), they should be kept lean and focused on a single, separate concern. In short, they should have a single reason to change." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-6960", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S6961", + "shortDescription": { + "text": "API Controllers should derive from ControllerBase instead of Controller" + }, + "fullDescription": { + "text": "In ASP.NET Core, controllers usually inherit either from ControllerBase or Controller. If a controller does not use any View-specific functionality, it is recommended to inherit from ControllerBase." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-6961", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S6962", + "shortDescription": { + "text": "You should pool HTTP connections with HttpClientFactory" + }, + "fullDescription": { + "text": "In frequently used code paths, such as controller actions, you should avoid using the HttpClient directly and opt for one of the IHttpClientFactory-based mechanisms instead. This way, you avoid wasting resources and creating performance overhead." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-6962", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S6964", + "shortDescription": { + "text": "Value type property used as input in a controller action should be nullable, required or annotated with the JsonRequiredAttribute to avoid under-posting." + }, + "fullDescription": { + "text": "\"Under-posting\" refers to a situation where a client sends less data than expected to the server during an HTTP request, for example when the client omits some properties from the request body that the server expects to receive." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-6964", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S6965", + "shortDescription": { + "text": "REST API actions should be annotated with an HTTP verb attribute" + }, + "fullDescription": { + "text": "When building a REST API, it’s recommended to annotate the controller actions with the available HTTP attributes to be precise about what your API supports." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-6965", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S6966", + "shortDescription": { + "text": "Awaitable method should be used" + }, + "fullDescription": { + "text": "In an async method, any blocking operations should be avoided." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-6966", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "0.071", + "executionTimeInPercentage": "1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S6967", + "shortDescription": { + "text": "ModelState.IsValid should be called in controller actions" + }, + "fullDescription": { + "text": "In the context of ASP.NET Core MVC web applications, both model binding and model validation are processes that take place prior to the execution of a controller action. It is imperative for the application to examine the ModelState.IsValid and respond accordingly." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-6967", + "properties": { + "category": "Critical Code Smell", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S6968", + "shortDescription": { + "text": "Actions that return a value should be annotated with ProducesResponseTypeAttribute containing the return type" + }, + "fullDescription": { + "text": "In an ASP.NET Core Web API, controller actions can optionally return a result value. If a controller action returns a value in the happy path, for example ControllerBase.Ok(Object), annotating the action with one of the [ProducesResponseType] overloads that describe the type is recommended." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-6968", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S7039", + "shortDescription": { + "text": "Content Security Policies should be restrictive" + }, + "fullDescription": { + "text": "The Content Security Policy (CSP) is a computer security standard that serves as an additional layer of protection against various types of attacks, including Cross-Site Scripting (XSS) and clickjacking. It provides a set of standard procedures for loading resources by user agents, which can help to mitigate the risk of content injection vulnerabilities." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-7039", + "properties": { + "category": "Major Vulnerability", + "executionTimeInSeconds": "0.012", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S818", + "shortDescription": { + "text": "Literal suffixes should be upper case" + }, + "fullDescription": { + "text": "Using upper case literal suffixes removes the potential ambiguity between \"1\" (digit 1) and \"l\" (letter el) for declaring literals." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-818", + "properties": { + "category": "Minor Code Smell", + "executionTimeInSeconds": "0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S881", + "shortDescription": { + "text": "Increment (++) and decrement (--) operators should not be used in a method call or mixed with other operators in an expression" + }, + "fullDescription": { + "text": "The use of increment and decrement operators in method calls or in combination with other arithmetic operators is not recommended, because:" + }, + "defaultConfiguration": { + "enabled": false + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-881", + "properties": { + "category": "Major Code Smell", + "isEverSuppressed": "true", + "suppressionKinds": [ + "external" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope" + ] + } + }, + { + "id": "S907", + "shortDescription": { + "text": "\"goto\" statement should not be used" + }, + "fullDescription": { + "text": "goto is an unstructured control flow statement. It makes code less readable and maintainable. Structured control flow statements such as if, for, while, continue or break should be used instead." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-907", + "properties": { + "category": "Major Code Smell", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S927", + "shortDescription": { + "text": "Parameter names should match base declaration and other partial definitions" + }, + "fullDescription": { + "text": "Parameters are part of the method signature and its identity." + }, + "helpUri": "https://rules.sonarsource.com/csharp/RSPEC-927", + "properties": { + "category": "Critical Code Smell", + "executionTimeInSeconds": "0.010", + "executionTimeInPercentage": "<1", + "tags": [ + "C#", + "MainSourceScope", + "TestSourceScope", + "SonarWay" + ] + } + }, + { + "id": "S9999-cpd", + "shortDescription": { + "text": "Copy-paste token calculator" + }, + "properties": { + "executionTimeInSeconds": "0.002", + "executionTimeInPercentage": "<1", + "tags": [ + "MainSourceScope", + "TestSourceScope", + "Utility", + "NotConfigurable" + ] + } + }, + { + "id": "S9999-log", + "shortDescription": { + "text": "Log generator" + }, + "properties": { + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "MainSourceScope", + "TestSourceScope", + "Utility", + "NotConfigurable" + ] + } + }, + { + "id": "S9999-metadata", + "shortDescription": { + "text": "File metadata generator" + }, + "properties": { + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "MainSourceScope", + "TestSourceScope", + "Utility", + "NotConfigurable" + ] + } + }, + { + "id": "S9999-metrics", + "shortDescription": { + "text": "Metrics calculator" + }, + "properties": { + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "MainSourceScope", + "TestSourceScope", + "Utility", + "NotConfigurable" + ] + } + }, + { + "id": "S9999-symbolRef", + "shortDescription": { + "text": "Symbol reference calculator" + }, + "properties": { + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "MainSourceScope", + "TestSourceScope", + "Utility", + "NotConfigurable" + ] + } + }, + { + "id": "S9999-telemetry", + "shortDescription": { + "text": "Telemetry generator" + }, + "properties": { + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "MainSourceScope", + "TestSourceScope", + "Utility", + "NotConfigurable" + ] + } + }, + { + "id": "S9999-testMethodDeclaration", + "shortDescription": { + "text": "Test method declarations generator" + }, + "properties": { + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "MainSourceScope", + "TestSourceScope", + "Utility", + "NotConfigurable" + ] + } + }, + { + "id": "S9999-token-type", + "shortDescription": { + "text": "Token type calculator" + }, + "properties": { + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "MainSourceScope", + "TestSourceScope", + "Utility", + "NotConfigurable" + ] + } + }, + { + "id": "S9999-warning", + "shortDescription": { + "text": "Analysis Warning generator" + }, + "properties": { + "executionTimeInSeconds": "0.020", + "executionTimeInPercentage": "<1", + "tags": [ + "MainSourceScope", + "TestSourceScope", + "Utility", + "NotConfigurable" + ] + } + }, + { + "id": "SYSLIB1045", + "shortDescription": { + "text": "Convert to 'GeneratedRegexAttribute'." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/syslib-diagnostics/syslib1045", + "properties": { + "category": "Performance", + "executionTimeInSeconds": "0.009", + "executionTimeInPercentage": "<1" + } + }, + { + "id": "SYSLIB1054", + "shortDescription": { + "text": "Use 'LibraryImportAttribute' instead of 'DllImportAttribute' to generate P/Invoke marshalling code at compile time" + }, + "fullDescription": { + "text": "Use 'LibraryImportAttribute' instead of 'DllImportAttribute' to generate P/Invoke marshalling code at compile time" + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/syslib-diagnostics/syslib1054", + "properties": { + "category": "Interoperability", + "executionTimeInSeconds": "0.009", + "executionTimeInPercentage": "<1" + } + }, + { + "id": "SYSLIB1055", + "shortDescription": { + "text": "Invalid 'CustomMarshallerAttribute' usage" + }, + "fullDescription": { + "text": "A type with a 'System.Runtime.InteropServices.CustomMarshallerAttribute' must specify a non-'null' managed type" + }, + "defaultConfiguration": { + "level": "error" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/syslib-diagnostics/syslib1055", + "properties": { + "category": "Usage", + "executionTimeInSeconds": "0.003", + "executionTimeInPercentage": "<1" + } + }, + { + "id": "SYSLIB1056", + "shortDescription": { + "text": "Specified marshaller type is invalid" + }, + "fullDescription": { + "text": "The unmanaged type for a custom marshaller must be a C# unmanaged type." + }, + "defaultConfiguration": { + "level": "error" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/syslib-diagnostics/syslib1056", + "properties": { + "category": "Usage", + "executionTimeInSeconds": "0.003", + "executionTimeInPercentage": "<1" + } + }, + { + "id": "SYSLIB1057", + "shortDescription": { + "text": "Marshaller type does not have the required shape" + }, + "fullDescription": { + "text": "A stateless value marshaller that supports marshalling from managed to unmanaged must provide a one-parameter 'ConvertToUnmanaged' method that takes the managed value as the parameter and returns a value of the 'unmanaged' type." + }, + "defaultConfiguration": { + "level": "error" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/syslib-diagnostics/syslib1057", + "properties": { + "category": "Usage", + "executionTimeInSeconds": "0.003", + "executionTimeInPercentage": "<1" + } + }, + { + "id": "SYSLIB1058", + "shortDescription": { + "text": "Invalid 'NativeMarshallingAttribute' usage" + }, + "fullDescription": { + "text": "An entry-point type for marshalling a given type must have a 'System.Runtime.InteropServices.CustomMarshallerAttribute' that specifies this type as the managed type." + }, + "defaultConfiguration": { + "level": "error" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/syslib-diagnostics/syslib1058", + "properties": { + "category": "Usage", + "executionTimeInSeconds": "0.002", + "executionTimeInPercentage": "<1" + } + }, + { + "id": "SYSLIB1060", + "shortDescription": { + "text": "Specified marshaller type is invalid" + }, + "fullDescription": { + "text": "A marshaller type must either be a stateless static class or a stateful value type. A non-static class is not allowed." + }, + "defaultConfiguration": { + "level": "error" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/syslib-diagnostics/syslib1060", + "properties": { + "category": "Usage", + "executionTimeInSeconds": "0.003", + "executionTimeInPercentage": "<1" + } + }, + { + "id": "SYSLIB1061", + "shortDescription": { + "text": "Marshaller type has incompatible method signatures" + }, + "fullDescription": { + "text": "The return type of 'GetPinnableReference' (after accounting for 'ref') must be blittable." + }, + "defaultConfiguration": { + "level": "error" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/syslib-diagnostics/syslib1061", + "properties": { + "category": "Usage", + "executionTimeInSeconds": "0.003", + "executionTimeInPercentage": "<1" + } + }, + { + "id": "SYSLIB1090", + "shortDescription": { + "text": "'GeneratedComInterfaceType' does not support the 'ComInterfaceType' value supplied to 'InterfaceTypeAttribute' on the same type." + }, + "fullDescription": { + "text": "Using 'GeneratedComInterfaceAttribute' and 'InterfaceTypeAttribute' is not supported with 'ComInterfaceType' value '{0}'." + }, + "defaultConfiguration": { + "level": "error" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/syslib-diagnostics/syslib1090", + "properties": { + "category": "ComInterfaceGenerator", + "executionTimeInSeconds": "0.001", + "executionTimeInPercentage": "<1" + } + }, + { + "id": "SYSLIB1096", + "shortDescription": { + "text": "Convert to 'GeneratedComInterface'" + }, + "fullDescription": { + "text": "Use 'GeneratedComInterfaceAttribute' instead of 'ComImportAttribute' to generate COM marshalling code at compile time" + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/syslib-diagnostics/syslib1096", + "properties": { + "category": "Interoperability", + "executionTimeInSeconds": "0.047", + "executionTimeInPercentage": "<1" + } + }, + { + "id": "SYSLIB1097", + "shortDescription": { + "text": "Add 'GeneratedComClassAttribute' to enable passing objects of this type to COM" + }, + "fullDescription": { + "text": "This type implements at least one type with the 'GeneratedComInterfaceAttribute' attribute. Add the 'GeneratedComClassAttribute' to enable passing this type to COM and exposing the COM interfaces for the types with the 'GeneratedComInterfaceAttribute' from objects of this type." + }, + "defaultConfiguration": { + "level": "note" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/syslib-diagnostics/syslib1097", + "properties": { + "category": "Interoperability", + "executionTimeInSeconds": "0.005", + "executionTimeInPercentage": "<1" + } + }, + { + "id": "SYSLIB1098", + "shortDescription": { + "text": ".NET COM hosting with 'EnableComHosting' does not support interfaces with the 'GeneratedComInterfaceAttribute'" + }, + "fullDescription": { + "text": ".NET COM hosting with 'EnableComHosting' only supports built-in COM interop. It does not support source-generated COM interop with 'GeneratedComInterfaceAttribute'." + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/syslib-diagnostics/syslib1098", + "properties": { + "category": "Interoperability", + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1" + } + }, + { + "id": "SYSLIB1099", + "shortDescription": { + "text": "COM Interop APIs on 'System.Runtime.InteropServices.Marshal' do not support source-generated COM" + }, + "fullDescription": { + "text": "COM Interop APIs on 'System.Runtime.InteropServices.Marshal' do not support source-generated COM and will fail at runtime" + }, + "helpUri": "https://learn.microsoft.com/dotnet/fundamentals/syslib-diagnostics/syslib1099", + "properties": { + "category": "Interoperability", + "executionTimeInSeconds": "0.012", + "executionTimeInPercentage": "<1" + } + }, + { + "id": "CS8619", + "shortDescription": { + "text": "Nullability of reference types in value doesn't match target type." + }, + "helpUri": "https://msdn.microsoft.com/query/roslyn.query?appId=roslyn&k=k(CS8619)", + "properties": { + "category": "Compiler", + "isEverSuppressed": "true", + "suppressionKinds": [ + "inSource" + ], + "executionTimeInSeconds": "<0.001", + "executionTimeInPercentage": "<1", + "tags": [ + "Compiler", + "Telemetry" + ] + } + } + ] + } + }, + "invocations": [ + { + "executionSuccessful": true, + "ruleConfigurationOverrides": [ + { + "descriptor": { + "id": "CA1416", + "index": 57 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "CA1417", + "index": 58 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "CA1418", + "index": 59 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "CA1420", + "index": 61 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "CA1422", + "index": 63 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "CA1514", + "index": 75 + }, + "configuration": { + "enabled": false + } + }, + { + "descriptor": { + "id": "CA1831", + "index": 112 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "CA1857", + "index": 138 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "CA1871", + "index": 152 + }, + "configuration": { + "enabled": false + } + }, + { + "descriptor": { + "id": "CA1872", + "index": 153 + }, + "configuration": { + "enabled": false + } + }, + { + "descriptor": { + "id": "CA2013", + "index": 161 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "CA2014", + "index": 162 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "CA2015", + "index": 163 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "CA2017", + "index": 165 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "CA2018", + "index": 166 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "CA2021", + "index": 169 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "CA2022", + "index": 170 + }, + "configuration": { + "enabled": false + } + }, + { + "descriptor": { + "id": "CA2200", + "index": 175 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "CA2247", + "index": 199 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "CA2255", + "index": 207 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "CA2256", + "index": 208 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "CA2257", + "index": 209 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "CA2258", + "index": 210 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "CA2259", + "index": 211 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "CA2260", + "index": 212 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "CA2261", + "index": 213 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "CA2262", + "index": 214 + }, + "configuration": { + "enabled": false + } + }, + { + "descriptor": { + "id": "CA2263", + "index": 215 + }, + "configuration": { + "enabled": false + } + }, + { + "descriptor": { + "id": "CA2264", + "index": 216 + }, + "configuration": { + "enabled": false + } + }, + { + "descriptor": { + "id": "CA2265", + "index": 217 + }, + "configuration": { + "enabled": false + } + }, + { + "descriptor": { + "id": "EF1001", + "index": 309 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "EF1002", + "index": 310 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S1006", + "index": 312 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S101", + "index": 313 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S1048", + "index": 316 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S1066", + "index": 319 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S1075", + "index": 322 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S108", + "index": 323 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S1104", + "index": 326 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S1110", + "index": 328 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S1116", + "index": 329 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S1117", + "index": 330 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S1118", + "index": 331 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S112", + "index": 332 + }, + "configuration": { + "level": "note" + } + }, + { + "descriptor": { + "id": "S1121", + "index": 333 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S1123", + "index": 334 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S1125", + "index": 335 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S1133", + "index": 338 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S1134", + "index": 339 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S1135", + "index": 340 + }, + "configuration": { + "level": "note" + } + }, + { + "descriptor": { + "id": "S1144", + "index": 341 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S1155", + "index": 344 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S1163", + "index": 345 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S1168", + "index": 346 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S1172", + "index": 347 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S1185", + "index": 348 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S1186", + "index": 349 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S1199", + "index": 351 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S1206", + "index": 353 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S1210", + "index": 355 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S1215", + "index": 356 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S1244", + "index": 360 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S125", + "index": 361 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S1264", + "index": 363 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S127", + "index": 364 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S1313", + "index": 369 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S1450", + "index": 373 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S1481", + "index": 376 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S1607", + "index": 378 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S1643", + "index": 379 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S1656", + "index": 380 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S1694", + "index": 382 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S1696", + "index": 383 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S1699", + "index": 385 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S1751", + "index": 386 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S1764", + "index": 387 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S1848", + "index": 389 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S1854", + "index": 390 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S1862", + "index": 392 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S1871", + "index": 393 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S1905", + "index": 394 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S1939", + "index": 395 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S1940", + "index": 396 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S1944", + "index": 397 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S1994", + "index": 398 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S2068", + "index": 399 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S2077", + "index": 400 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S2092", + "index": 401 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S2094", + "index": 402 + }, + "configuration": { + "enabled": false + } + }, + { + "descriptor": { + "id": "S2114", + "index": 403 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S2115", + "index": 404 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S2123", + "index": 405 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S2139", + "index": 406 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S2166", + "index": 409 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S2178", + "index": 410 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S2183", + "index": 411 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S2184", + "index": 412 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S2187", + "index": 413 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S2190", + "index": 414 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S2198", + "index": 416 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S2201", + "index": 417 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S2219", + "index": 418 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S2223", + "index": 420 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S2225", + "index": 421 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S2234", + "index": 422 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S2245", + "index": 423 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S2251", + "index": 424 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S2252", + "index": 425 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S2257", + "index": 426 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S2275", + "index": 427 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S2290", + "index": 428 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S2291", + "index": 429 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S2292", + "index": 430 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S2306", + "index": 432 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S2325", + "index": 433 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S2326", + "index": 434 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S2328", + "index": 436 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S2344", + "index": 441 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S2345", + "index": 442 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S2346", + "index": 443 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S2365", + "index": 446 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S2368", + "index": 447 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S2372", + "index": 448 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S2376", + "index": 449 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S2386", + "index": 450 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S2445", + "index": 454 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S2479", + "index": 455 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S2486", + "index": 456 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S2551", + "index": 457 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S2612", + "index": 458 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S2629", + "index": 459 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S2674", + "index": 460 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S2681", + "index": 461 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S2688", + "index": 462 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S2692", + "index": 463 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S2696", + "index": 464 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S2699", + "index": 465 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S2701", + "index": 466 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S2737", + "index": 467 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S2743", + "index": 468 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S2755", + "index": 469 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S2757", + "index": 470 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S2761", + "index": 472 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S2857", + "index": 473 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S2925", + "index": 474 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S2930", + "index": 475 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S2933", + "index": 477 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S2934", + "index": 478 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S2953", + "index": 480 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S2955", + "index": 481 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S2970", + "index": 482 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S2971", + "index": 483 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S2995", + "index": 484 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S2996", + "index": 485 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S2997", + "index": 486 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3005", + "index": 487 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3010", + "index": 488 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3011", + "index": 489 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3060", + "index": 492 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3063", + "index": 493 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3168", + "index": 494 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3169", + "index": 495 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3172", + "index": 496 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3217", + "index": 499 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3218", + "index": 500 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3220", + "index": 501 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3236", + "index": 504 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3237", + "index": 505 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3241", + "index": 507 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3244", + "index": 509 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3246", + "index": 510 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3247", + "index": 511 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3249", + "index": 512 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3251", + "index": 513 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3256", + "index": 516 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3260", + "index": 518 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3261", + "index": 519 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3262", + "index": 520 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3263", + "index": 521 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3264", + "index": 522 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3265", + "index": 523 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3267", + "index": 524 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3330", + "index": 525 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3343", + "index": 526 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3346", + "index": 527 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3358", + "index": 529 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3363", + "index": 530 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3376", + "index": 532 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3397", + "index": 533 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3398", + "index": 534 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3400", + "index": 535 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3415", + "index": 536 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3427", + "index": 538 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3431", + "index": 539 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3433", + "index": 540 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3440", + "index": 541 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3442", + "index": 543 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3443", + "index": 544 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3444", + "index": 545 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3445", + "index": 546 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3447", + "index": 547 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3449", + "index": 548 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3450", + "index": 549 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3451", + "index": 550 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3453", + "index": 551 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3456", + "index": 552 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3457", + "index": 553 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3458", + "index": 554 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3459", + "index": 555 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3464", + "index": 556 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3466", + "index": 557 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3597", + "index": 559 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3598", + "index": 560 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3600", + "index": 561 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3603", + "index": 562 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3604", + "index": 563 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3610", + "index": 564 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3626", + "index": 565 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3869", + "index": 568 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3871", + "index": 569 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3875", + "index": 572 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3877", + "index": 574 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3878", + "index": 575 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3881", + "index": 577 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3885", + "index": 579 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3887", + "index": 580 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3889", + "index": 581 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3897", + "index": 582 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3903", + "index": 585 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3904", + "index": 586 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3923", + "index": 590 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3925", + "index": 591 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3926", + "index": 592 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3927", + "index": 593 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3928", + "index": 594 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3963", + "index": 598 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3971", + "index": 600 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3972", + "index": 601 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3973", + "index": 602 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3981", + "index": 603 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3984", + "index": 604 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3993", + "index": 607 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S3998", + "index": 612 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S4015", + "index": 617 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S4019", + "index": 621 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S4035", + "index": 627 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S4036", + "index": 628 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S4050", + "index": 634 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S4052", + "index": 635 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S4061", + "index": 642 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S4070", + "index": 644 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S4136", + "index": 645 + }, + "configuration": { + "level": "note" + } + }, + { + "descriptor": { + "id": "S4143", + "index": 646 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S4144", + "index": 647 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S4159", + "index": 648 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S4200", + "index": 649 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S4201", + "index": 650 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S4210", + "index": 651 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S4211", + "index": 652 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S4220", + "index": 655 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S4260", + "index": 658 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S4275", + "index": 660 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S4277", + "index": 661 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S4423", + "index": 662 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S4426", + "index": 663 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S4428", + "index": 664 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S4433", + "index": 665 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S4456", + "index": 666 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S4487", + "index": 669 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S4502", + "index": 670 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S4507", + "index": 671 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S4524", + "index": 672 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S4545", + "index": 673 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S4581", + "index": 674 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S4583", + "index": 675 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S4586", + "index": 676 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S4635", + "index": 677 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S4663", + "index": 678 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S4790", + "index": 679 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S4792", + "index": 680 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S4830", + "index": 681 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S5034", + "index": 682 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S5042", + "index": 683 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S5122", + "index": 684 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S5332", + "index": 685 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S5344", + "index": 686 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S5443", + "index": 687 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S5445", + "index": 688 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S5542", + "index": 689 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S5547", + "index": 690 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S5659", + "index": 691 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S5693", + "index": 692 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S5753", + "index": 693 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S5766", + "index": 694 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S5856", + "index": 695 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S6377", + "index": 697 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S6418", + "index": 698 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S6419", + "index": 699 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S6420", + "index": 700 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S6422", + "index": 702 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S6424", + "index": 704 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S6444", + "index": 705 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S6561", + "index": 708 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S6562", + "index": 709 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S6575", + "index": 712 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S6580", + "index": 713 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S6588", + "index": 715 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S6607", + "index": 719 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S6608", + "index": 720 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S6609", + "index": 721 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S6610", + "index": 722 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S6612", + "index": 723 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S6613", + "index": 724 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S6617", + "index": 725 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S6618", + "index": 726 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S6640", + "index": 727 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S6667", + "index": 729 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S6668", + "index": 730 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S6670", + "index": 732 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S6672", + "index": 733 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S6673", + "index": 734 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S6674", + "index": 735 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S6675", + "index": 736 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S6677", + "index": 737 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S6678", + "index": 738 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S6797", + "index": 739 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S6798", + "index": 740 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S6800", + "index": 741 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S6930", + "index": 744 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S6931", + "index": 745 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S6932", + "index": 746 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S6934", + "index": 747 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S6960", + "index": 748 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S6961", + "index": 749 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S6962", + "index": 750 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S6964", + "index": 751 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S6965", + "index": 752 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S6966", + "index": 753 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S6967", + "index": 754 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S6968", + "index": 755 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S7039", + "index": 756 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S818", + "index": 757 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S907", + "index": 759 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "S927", + "index": 760 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "SYSLIB1098", + "index": 781 + }, + "configuration": { + "level": "error" + } + }, + { + "descriptor": { + "id": "SYSLIB1099", + "index": 782 + }, + "configuration": { + "level": "error" + } + } + ] + } + ], + "columnKind": "utf16CodeUnits" + } + ] +} \ No newline at end of file diff --git a/Application/EdFi.Ods.AdminApi.AdminConsole.UnitTests/EdFi.Ods.AdminApi.AdminConsole.UnitTests.csproj b/Application/EdFi.Ods.AdminApi.AdminConsole.UnitTests/EdFi.Ods.AdminApi.AdminConsole.UnitTests.csproj index 5ebf82ffb..5d3b56796 100644 --- a/Application/EdFi.Ods.AdminApi.AdminConsole.UnitTests/EdFi.Ods.AdminApi.AdminConsole.UnitTests.csproj +++ b/Application/EdFi.Ods.AdminApi.AdminConsole.UnitTests/EdFi.Ods.AdminApi.AdminConsole.UnitTests.csproj @@ -33,4 +33,8 @@ + + + + diff --git a/Application/EdFi.Ods.AdminApi.AdminConsole/Infrastructure/Services/Instances/Models/IInstanceRequestModel.cs b/Application/EdFi.Ods.AdminApi.AdminConsole/Infrastructure/Services/Instances/Models/IInstanceRequestModel.cs index c79aa39b2..de7b68254 100644 --- a/Application/EdFi.Ods.AdminApi.AdminConsole/Infrastructure/Services/Instances/Models/IInstanceRequestModel.cs +++ b/Application/EdFi.Ods.AdminApi.AdminConsole/Infrastructure/Services/Instances/Models/IInstanceRequestModel.cs @@ -17,7 +17,7 @@ public interface IInstanceRequestModel ICollection? OdsInstanceDerivatives { get; } byte[]? Credentials { get; } - public string? Status { get; set; } + string? Status { get; set; } } public class OdsInstanceContextModel diff --git a/Application/EdFi.Ods.AdminApi.AdminConsole/Infrastructure/Services/Tenants/TenantService.cs b/Application/EdFi.Ods.AdminApi.AdminConsole/Infrastructure/Services/Tenants/TenantService.cs index 4b122bfa8..177f96bf6 100644 --- a/Application/EdFi.Ods.AdminApi.AdminConsole/Infrastructure/Services/Tenants/TenantService.cs +++ b/Application/EdFi.Ods.AdminApi.AdminConsole/Infrastructure/Services/Tenants/TenantService.cs @@ -21,11 +21,11 @@ public interface IAdminConsoleTenantsService Task GetTenantByTenantIdAsync(int tenantId); } -public class TenantService(IOptionsSnapshot options, - IMemoryCache memoryCache) : IAdminConsoleTenantsService +public class TenantService(IOptionsMonitor options, IMemoryCache memoryCache) + : IAdminConsoleTenantsService { private const string ADMIN_DB_KEY = "EdFi_Admin"; - protected AppSettingsFile _appSettings = options.Value; + protected AppSettingsFile _appSettings = options.CurrentValue; private readonly IMemoryCache _memoryCache = memoryCache; private static readonly ILog _log = LogManager.GetLogger(typeof(TenantService)); diff --git a/Application/EdFi.Ods.AdminApi.Common/Settings/AppSettings.cs b/Application/EdFi.Ods.AdminApi.Common/Settings/AppSettings.cs index 9c9d4e7d2..74307c084 100644 --- a/Application/EdFi.Ods.AdminApi.Common/Settings/AppSettings.cs +++ b/Application/EdFi.Ods.AdminApi.Common/Settings/AppSettings.cs @@ -26,7 +26,10 @@ public class AppSettings public bool PreventDuplicateApplications { get; set; } public bool EnableAdminConsoleAPI { get; set; } public bool IgnoresCertificateErrors { get; set; } - public bool EnableApplicationResetEndpoint { get; set; } + public bool EnableApplicationResetEndpoint { get; set; } + public bool OverrideExistingDatabase { get; set; } + public string? InstanceManagementFrequencyInMinutes { get; set; } + public string? SqlServerBakFile { get; set; } } public class SwaggerSettings diff --git a/Application/EdFi.Ods.AdminApi.DBTests/Database/CommandTests/AddApiClientCommandTests.cs b/Application/EdFi.Ods.AdminApi.DBTests/Database/CommandTests/AddApiClientCommandTests.cs index e4db60d34..e12ceb965 100644 --- a/Application/EdFi.Ods.AdminApi.DBTests/Database/CommandTests/AddApiClientCommandTests.cs +++ b/Application/EdFi.Ods.AdminApi.DBTests/Database/CommandTests/AddApiClientCommandTests.cs @@ -5,8 +5,6 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Threading.Tasks; using EdFi.Admin.DataAccess.Models; using EdFi.Ods.AdminApi.Common.Settings; @@ -20,20 +18,21 @@ namespace EdFi.Ods.AdminApi.DBTests.Database.CommandTests; internal class AddApiClientCommandTests : PlatformUsersContextTestBase { private IOptions _options { get; set; } - private int applicationId { get; set; } [SetUp] - public virtual async Task SetUp() + public new virtual async Task SetUp() { - AppSettings appSettings = new AppSettings(); - appSettings.PreventDuplicateApplications = false; + AppSettings appSettings = new() + { + PreventDuplicateApplications = false + }; _options = Options.Create(appSettings); await Task.Yield(); var vendor = new Vendor { VendorId = 0, - VendorNamespacePrefixes = new List { new VendorNamespacePrefix { NamespacePrefix = "http://tests.com" } }, + VendorNamespacePrefixes = [new() { NamespacePrefix = "http://tests.com" }], VendorName = "Integration Tests" }; @@ -47,8 +46,6 @@ public virtual async Task SetUp() }; Save(application); - - applicationId = application.ApplicationId; } [Test] @@ -62,7 +59,7 @@ public void ShouldFailForInvalidApplication() Name = "Test ApiClient", ApplicationId = 0, IsApproved = true, - OdsInstanceIds = new List { 1, 2 } + OdsInstanceIds = [1, 2] }; Assert.Throws(() => command.Execute(newApiClient, _options)); @@ -75,7 +72,7 @@ public void ShouldCreateApiClientWithOdsInstances() var vendor = new Vendor { VendorId = 0, - VendorNamespacePrefixes = new List { new VendorNamespacePrefix { NamespacePrefix = "http://tests.com" } }, + VendorNamespacePrefixes = [new() { NamespacePrefix = "http://tests.com" }], VendorName = "Integration Tests" }; @@ -98,7 +95,7 @@ public void ShouldCreateApiClientWithOdsInstances() Name = "Test ApiClient", ApplicationId = application.ApplicationId, IsApproved = true, - OdsInstanceIds = new List { 1, 2 } + OdsInstanceIds = [1, 2] }; command.Execute(newApiClient, _options); @@ -111,7 +108,7 @@ public void ShouldCreateApiClientWithOutOdsInstances() var vendor = new Vendor { VendorId = 0, - VendorNamespacePrefixes = new List { new VendorNamespacePrefix { NamespacePrefix = "http://tests.com" } }, + VendorNamespacePrefixes = [new() { NamespacePrefix = "http://tests.com" }], VendorName = "Integration Tests" }; diff --git a/Application/EdFi.Ods.AdminApi.DBTests/Database/CommandTests/EditApiClientCommandTests.cs b/Application/EdFi.Ods.AdminApi.DBTests/Database/CommandTests/EditApiClientCommandTests.cs index a23c415b1..86feca1cf 100644 --- a/Application/EdFi.Ods.AdminApi.DBTests/Database/CommandTests/EditApiClientCommandTests.cs +++ b/Application/EdFi.Ods.AdminApi.DBTests/Database/CommandTests/EditApiClientCommandTests.cs @@ -9,13 +9,9 @@ using System.Threading.Tasks; using EdFi.Admin.DataAccess.Models; using EdFi.Ods.AdminApi.Common.Infrastructure; -using EdFi.Ods.AdminApi.Common.Settings; using EdFi.Ods.AdminApi.Infrastructure.Database.Commands; -using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.Options; using NUnit.Framework; using Shouldly; -using Profile = EdFi.Admin.DataAccess.Models.Profile; using VendorUser = EdFi.Admin.DataAccess.Models.User; namespace EdFi.Ods.AdminApi.DBTests.Database.CommandTests; @@ -30,14 +26,9 @@ internal class EditApiClientCommandTests : PlatformUsersContextTestBase private OdsInstance _odsInstance; private ApiClientOdsInstance _apiClientOdsInstance; - private IOptions _options { get; set; } - [SetUp] - public virtual async Task SetUp() + public new virtual async Task SetUp() { - AppSettings appSettings = new AppSettings(); - appSettings.PreventDuplicateApplications = false; - _options = Options.Create(appSettings); await Task.Yield(); } @@ -52,7 +43,7 @@ private void SetupTestEntities() _vendor = new Vendor { - VendorNamespacePrefixes = new List { new VendorNamespacePrefix { NamespacePrefix = "http://tests.com" } }, + VendorNamespacePrefixes = [new() { NamespacePrefix = "http://tests.com" }], VendorName = "Integration Tests" }; @@ -190,7 +181,7 @@ public void ShouldAddOdsInstancesIfNew() ApplicationId = _application.ApplicationId, Name = _apiClient.Name, IsApproved = true, - OdsInstanceIds = new List { _odsInstance.OdsInstanceId, _newOdsInstance.OdsInstanceId } + OdsInstanceIds = [_odsInstance.OdsInstanceId, _newOdsInstance.OdsInstanceId] }; Transaction(usersContext => diff --git a/Application/EdFi.Ods.AdminApi.DBTests/EdFi.Ods.AdminApi.DBTests.csproj b/Application/EdFi.Ods.AdminApi.DBTests/EdFi.Ods.AdminApi.DBTests.csproj index 33a6a7f49..d5477e72b 100644 --- a/Application/EdFi.Ods.AdminApi.DBTests/EdFi.Ods.AdminApi.DBTests.csproj +++ b/Application/EdFi.Ods.AdminApi.DBTests/EdFi.Ods.AdminApi.DBTests.csproj @@ -35,4 +35,7 @@ Always + + + \ No newline at end of file diff --git a/Application/EdFi.Ods.AdminApi.UnitTests/EdFi.Ods.AdminApi.UnitTests.csproj b/Application/EdFi.Ods.AdminApi.UnitTests/EdFi.Ods.AdminApi.UnitTests.csproj index 6363b7252..3add5bc8f 100644 --- a/Application/EdFi.Ods.AdminApi.UnitTests/EdFi.Ods.AdminApi.UnitTests.csproj +++ b/Application/EdFi.Ods.AdminApi.UnitTests/EdFi.Ods.AdminApi.UnitTests.csproj @@ -15,7 +15,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive @@ -25,4 +25,7 @@ + + + diff --git a/Application/EdFi.Ods.AdminApi/E2E Tests/gh-action-setup/.automation_api_idp_mssql.env b/Application/EdFi.Ods.AdminApi/E2E Tests/gh-action-setup/.automation_api_idp_mssql.env index ce3d8073d..a4f12e207 100644 --- a/Application/EdFi.Ods.AdminApi/E2E Tests/gh-action-setup/.automation_api_idp_mssql.env +++ b/Application/EdFi.Ods.AdminApi/E2E Tests/gh-action-setup/.automation_api_idp_mssql.env @@ -41,6 +41,8 @@ KEYCLOAK_HOSTNAME_STRICT_HTTPS=true KEYCLOAK_HEALTH_ENABLED=true KEYCLOAK_ADMIN_CONSOLE_REALM=edfi-admin-console +DATABASEPROVIDER=SqlServer +CONNECTION_STRINGS_PROVIDER=SqlServer # Ods Api TAG=7.1 diff --git a/Application/EdFi.Ods.AdminApi/E2E Tests/gh-action-setup/.automation_api_idp_pgsql.env b/Application/EdFi.Ods.AdminApi/E2E Tests/gh-action-setup/.automation_api_idp_pgsql.env index 67a601d80..f714d7d1f 100644 --- a/Application/EdFi.Ods.AdminApi/E2E Tests/gh-action-setup/.automation_api_idp_pgsql.env +++ b/Application/EdFi.Ods.AdminApi/E2E Tests/gh-action-setup/.automation_api_idp_pgsql.env @@ -41,6 +41,8 @@ KEYCLOAK_HOSTNAME_STRICT_HTTPS=true KEYCLOAK_HEALTH_ENABLED=true KEYCLOAK_ADMIN_CONSOLE_REALM=edfi-admin-console +DATABASEPROVIDER=Npgsql +CONNECTION_STRINGS_PROVIDER=Npgsql # Ods Api TAG=7.1 diff --git a/Application/EdFi.Ods.AdminApi/E2E Tests/gh-action-setup/.automation_mssql.env b/Application/EdFi.Ods.AdminApi/E2E Tests/gh-action-setup/.automation_mssql.env index eb03e76bf..2a217470f 100644 --- a/Application/EdFi.Ods.AdminApi/E2E Tests/gh-action-setup/.automation_mssql.env +++ b/Application/EdFi.Ods.AdminApi/E2E Tests/gh-action-setup/.automation_mssql.env @@ -26,6 +26,8 @@ API_INTERNAL_URL=http://${ODS_VIRTUAL_NAME} ADMIN_API_HEALTHCHECK_TEST="wget -nv -t1 --spider http://${ADMIN_API_VIRTUAL_NAME}/health || exit 1" +DATABASEPROVIDER=SqlServer +CONNECTION_STRINGS_PROVIDER=SqlServer # Ods Api TAG=7.1 diff --git a/Application/EdFi.Ods.AdminApi/E2E Tests/gh-action-setup/.automation_pgsql.env b/Application/EdFi.Ods.AdminApi/E2E Tests/gh-action-setup/.automation_pgsql.env index 8c63f80d5..5c2c90a02 100644 --- a/Application/EdFi.Ods.AdminApi/E2E Tests/gh-action-setup/.automation_pgsql.env +++ b/Application/EdFi.Ods.AdminApi/E2E Tests/gh-action-setup/.automation_pgsql.env @@ -23,6 +23,8 @@ API_INTERNAL_URL=http://${ODS_VIRTUAL_NAME} ADMIN_API_HEALTHCHECK_TEST="wget -nv -t1 --spider http://${ADMIN_API_VIRTUAL_NAME}/health || exit 1" +DATABASEPROVIDER=Npgsql +CONNECTION_STRINGS_PROVIDER=Npgsql # Ods Api TAG=7.1 diff --git a/Application/EdFi.Ods.AdminApi/EdFi.Ods.AdminApi.csproj b/Application/EdFi.Ods.AdminApi/EdFi.Ods.AdminApi.csproj index 944336b95..6eb1a975e 100644 --- a/Application/EdFi.Ods.AdminApi/EdFi.Ods.AdminApi.csproj +++ b/Application/EdFi.Ods.AdminApi/EdFi.Ods.AdminApi.csproj @@ -43,6 +43,9 @@ runtime; build; native; contentfiles; analyzers; buildtransitive all + + + @@ -51,6 +54,7 @@ + diff --git a/Application/EdFi.Ods.AdminApi/Features/ClaimSets/ClaimSetModel.cs b/Application/EdFi.Ods.AdminApi/Features/ClaimSets/ClaimSetModel.cs index 7b60e9dd1..275a8fbd1 100644 --- a/Application/EdFi.Ods.AdminApi/Features/ClaimSets/ClaimSetModel.cs +++ b/Application/EdFi.Ods.AdminApi/Features/ClaimSets/ClaimSetModel.cs @@ -1,108 +1,128 @@ -// SPDX-License-Identifier: Apache-2.0 -// Licensed to the Ed-Fi Alliance under one or more agreements. -// The Ed-Fi Alliance licenses this file to you under the Apache License, Version 2.0. -// See the LICENSE and NOTICES files in the project root for more information. - -using EdFi.Ods.AdminApi.Features.Applications; -using EdFi.Ods.AdminApi.Infrastructure.ClaimSetEditor; -using EdFi.Ods.AdminApi.Infrastructure.Documentation; using Swashbuckle.AspNetCore.Annotations; -using System.Linq; using System.Text.Json.Serialization; -namespace EdFi.Ods.AdminApi.Features.ClaimSets; - -[SwaggerSchema(Title = "ClaimSet")] -public class ClaimSetModel -{ - public int Id { get; set; } - public string? Name { get; set; } - [JsonPropertyName("_isSystemReserved")] - [SwaggerSchema(ReadOnly = true)] - public bool IsSystemReserved { get; set; } - [JsonPropertyName("_applications")] - [SwaggerSchema(ReadOnly = true)] - public List Applications { get; set; } = new(); -} - -[SwaggerSchema(Title = "ClaimSetWithResources")] -public class ClaimSetDetailsModel : ClaimSetModel -{ - public List ResourceClaims { get; set; } = new(); -} - - -[SwaggerSchema(Title = "ClaimSetResourceClaim")] -public class ClaimSetResourceClaimModel -{ - [SwaggerSchema(ReadOnly = true)] - public int Id { get; set; } - public string? Name { get; set; } - public List? Actions { get; set; } - - [JsonPropertyName("_defaultAuthorizationStrategiesForCRUD")] - [SwaggerSchema(ReadOnly = true)] - public List DefaultAuthorizationStrategiesForCRUD { get; set; } - - public List AuthorizationStrategyOverridesForCRUD { get; set; } - - [SwaggerSchema(Description = "Children are collection of ResourceClaim")] - public List Children { get; set; } - - public ClaimSetResourceClaimModel() - { - Children = new List(); - DefaultAuthorizationStrategiesForCRUD = new List(); - AuthorizationStrategyOverridesForCRUD = new List(); - Actions = new List(); - } -} - -public class ChildrenClaimSetResource : ClaimSetResourceClaimModel -{ - [SwaggerSchema(Description = "Children are collection of ResourceClaim")] - public new ClaimSetResourceClaimModel Children { get; set; } - - public ChildrenClaimSetResource() - { - Children = new ClaimSetResourceClaimModel(); - } -} -[SwaggerSchema(Title = "ResourceClaimModel")] -public class ResourceClaimModel -{ - public int Id { get; set; } - public string? Name { get; set; } - public int? ParentId { get; set; } - public string? ParentName { get; set; } - [SwaggerSchema(Description = "Children are collection of SimpleResourceClaimModel")] - public List Children { get; set; } - public ResourceClaimModel() - { - Children = new List(); - } -} - -public class EditClaimSetModel : IEditClaimSetModel -{ - public string? ClaimSetName { get; set; } - - public int ClaimSetId { get; set; } -} - -public class UpdateResourcesOnClaimSetModel : IUpdateResourcesOnClaimSetModel -{ - public int ClaimSetId { get; set; } - - public List? ResourceClaims { get; set; } = new List(); -} - -public class DeleteClaimSetModel : IDeleteClaimSetModel -{ - public string? Name { get; set; } - - public int Id { get; set; } -} -public interface IResourceClaimOnClaimSetRequest -{ - int ClaimSetId { get; } - int ResourceClaimId { get; } - public List? ResourceClaimActions { get; } -} +// SPDX-License-Identifier: Apache-2.0 +// Licensed to the Ed-Fi Alliance under one or more agreements. +// The Ed-Fi Alliance licenses this file to you under the Apache License, Version 2.0. +// See the LICENSE and NOTICES files in the project root for more information. + +using EdFi.Ods.AdminApi.Features.Applications; + +using EdFi.Ods.AdminApi.Infrastructure.ClaimSetEditor; +using EdFi.Ods.AdminApi.Infrastructure.Documentation; +using Swashbuckle.AspNetCore.Annotations; +using System.Linq; +using System.Text.Json.Serialization; + +namespace EdFi.Ods.AdminApi.Features.ClaimSets; + +[SwaggerSchema(Title = "ClaimSet")] +public class ClaimSetModel +{ + public int Id { get; set; } + public string? Name { get; set; } + + [JsonPropertyName("_isSystemReserved")] + + [SwaggerSchema(ReadOnly = true)] + public bool IsSystemReserved { get; set; } + + [JsonPropertyName("_applications")] + + [SwaggerSchema(ReadOnly = true)] + + public List Applications { get; set; } = new(); +} + + +[SwaggerSchema(Title = "ClaimSetWithResources")] +public class ClaimSetDetailsModel : ClaimSetModel +{ + public List ResourceClaims { get; set; } = new(); +} + + + +[SwaggerSchema(Title = "ClaimSetResourceClaim")] +public class ClaimSetResourceClaimModel +{ + [SwaggerSchema(ReadOnly = true)] + public int Id { get; set; } + public string? Name { get; set; } + public List? Actions { get; set; } + + [JsonPropertyName("_defaultAuthorizationStrategiesForCRUD")] + [SwaggerSchema(ReadOnly = true)] + public List DefaultAuthorizationStrategiesForCRUD { get; set; } + + public List AuthorizationStrategyOverridesForCRUD { get; set; } + + [SwaggerSchema(Description = "Children are collection of ResourceClaim")] + public List Children { get; set; } + + public ClaimSetResourceClaimModel() + { + Children = new List(); + DefaultAuthorizationStrategiesForCRUD = new List(); + AuthorizationStrategyOverridesForCRUD = new List(); + Actions = new List(); + } +} + +public class ChildrenClaimSetResource : ClaimSetResourceClaimModel +{ + [SwaggerSchema(Description = "Children are collection of ResourceClaim")] + public new ClaimSetResourceClaimModel Children { get; set; } + + public ChildrenClaimSetResource() + { + Children = new ClaimSetResourceClaimModel(); + } +} + +[SwaggerSchema(Title = "ResourceClaimModel")] +public class ResourceClaimModel +{ + public int Id { get; set; } + public string? Name { get; set; } + + public int? ParentId { get; set; } + + public string? ParentName { get; set; } + + [SwaggerSchema(Description = "Children are collection of SimpleResourceClaimModel")] + public List Children { get; set; } + public ResourceClaimModel() + { + Children = new List(); + } +} + +public class EditClaimSetModel : IEditClaimSetModel +{ + public string? ClaimSetName { get; set; } + + public int ClaimSetId { get; set; } +} + +public class UpdateResourcesOnClaimSetModel : IUpdateResourcesOnClaimSetModel +{ + public int ClaimSetId { get; set; } + + public List? ResourceClaims { get; set; } = new List(); +} + +public class DeleteClaimSetModel : IDeleteClaimSetModel +{ + public string? Name { get; set; } + + public int Id { get; set; } +} + +public interface IResourceClaimOnClaimSetRequest +{ + int ClaimSetId { get; } + + int ResourceClaimId { get; } + + List? ResourceClaimActions { get; } + +} + diff --git a/Application/EdFi.Ods.AdminApi/Features/InstanceManagement/InstanceManagementService.cs b/Application/EdFi.Ods.AdminApi/Features/InstanceManagement/InstanceManagementService.cs new file mode 100644 index 000000000..43c7f2339 --- /dev/null +++ b/Application/EdFi.Ods.AdminApi/Features/InstanceManagement/InstanceManagementService.cs @@ -0,0 +1,130 @@ +// SPDX-License-Identifier: Apache-2.0 +// Licensed to the Ed-Fi Alliance under one or more agreements. +// The Ed-Fi Alliance licenses this file to you under the Apache License, Version 2.0. +// See the LICENSE and NOTICES files in the project root for more information. + +using EdFi.AdminConsole.InstanceMgrWorker.Configuration.Provisioners; +using EdFi.Ods.AdminApi.AdminConsole.Infrastructure.Services.Instances.Commands; +using EdFi.Ods.AdminApi.AdminConsole.Infrastructure.Services.Instances.Queries; +using EdFi.Ods.AdminApi.AdminConsole.Infrastructure.Services.Tenants; +using EdFi.Ods.AdminApi.Common.Settings; + +namespace EdFi.Ods.AdminApi.Features.InstanceManagement; + +public interface IInstanceManagementService +{ + Task RunAsync(CancellationToken cancellationToken); +} + +public class InstanceManagementService( +ILogger logger, +IAdminConsoleTenantsService adminConsoleTenantsService, +IGetInstancesQuery getInstancesQuery, +ICompleteInstanceCommand completeInstanceCommand, +IDeletedInstanceCommand deletedInstanceCommand, +IInstanceProvisioner instanceProvisioner, +AppSettings appSettings) : IInstanceManagementService +{ + private readonly ILogger _logger = logger; + private readonly IAdminConsoleTenantsService _adminConsoleTenantsService = adminConsoleTenantsService; + private readonly IGetInstancesQuery _getInstancesQuery = getInstancesQuery; + private readonly ICompleteInstanceCommand _completeInstanceCommand = completeInstanceCommand; + private readonly IDeletedInstanceCommand _deletedInstanceCommand = deletedInstanceCommand; + private readonly IInstanceProvisioner _instanceProvisioner = instanceProvisioner; + private readonly AppSettings _appSettings = appSettings; + + public async Task RunAsync(CancellationToken cancellationToken) + { + await CreateInstances(); + await DeleteInstances(); + } + + private async Task CreateInstances() + { + _logger.LogInformation("Get tenants on Admin Api."); + var tenants = await _adminConsoleTenantsService.GetTenantsAsync(); + + if (tenants.Count == 0) + _logger.LogInformation("No tenants returned from Admin Api."); + else + { + foreach (var tenantName in tenants.Select(tenant => tenant.Document is IDictionary document && document.TryGetValue("Name", out object? value) ? value?.ToString() : null)) + { + if (!string.IsNullOrEmpty(tenantName)) + { + _instanceProvisioner.Tenant = tenantName; + var instances = await _getInstancesQuery.Execute(tenantName, AdminConsole.Infrastructure.DataAccess.Models.InstanceStatus.Pending.ToString() + ); + + if (instances == null || !instances.Any()) + { + _logger.LogInformation("No instances pending to create found on Admin Api for tenant {TenantName}", tenantName); + } + else + { + foreach (var instance in instances) + { + var instanceName = instance.InstanceName; + + if (!string.IsNullOrWhiteSpace(instanceName)) + { + // Checks if the instance exists or it is a new instance + if (!_appSettings.OverrideExistingDatabase + && await _instanceProvisioner.CheckDatabaseExists(instanceName)) + { + _logger.LogInformation("Processing instance with name: {InstanceName} already exists. Skipping processing", instanceName ?? ""); + continue; + } + _logger.LogInformation("Processing instance with name: {InstanceName}", instanceName); + + await _instanceProvisioner.AddDbInstanceAsync(instanceName, DbInstanceType.Minimal); + + await _completeInstanceCommand.Execute(instance.Id, _instanceProvisioner.GetOdsConnectionString(instanceName)); + + _logger.LogInformation("Completed processing instance with name: {InstanceName}", instanceName); + } + } + _logger.LogInformation("Process completed."); + } + } + } + } + } + + private async Task DeleteInstances() + { + var tenants = await _adminConsoleTenantsService.GetTenantsAsync(); + var tenantNames = tenants.Select(tenant => tenant.Document is IDictionary document && document.TryGetValue("Name", out object? value) ? value?.ToString() : null).ToList(); + foreach (var tenantName in tenantNames) + { + if (!string.IsNullOrEmpty(tenantName)) + { + _instanceProvisioner.Tenant = tenantName; + + var instances = await _getInstancesQuery.Execute(tenantName, AdminConsole.Infrastructure.DataAccess.Models.InstanceStatus.Pending_Delete.ToString()); + + if (instances == null || !instances.Any()) + { + _logger.LogInformation("No instances found on Admin Api with status == PENDING_DELETE. For Tenant {TenantName}", tenantName); + continue; + } + + foreach (var instanceData in instances) + { + try + { + _logger.LogInformation("Deleting instance: {InstanceName}", instanceData.InstanceName); + await _instanceProvisioner.DeleteDbInstancesAsync(instanceData.InstanceName); + // Call POST /adminconsole/instances/{id}/deleted to mark the Instance as DELETED + await _deletedInstanceCommand.Execute(instanceData.Id); + _logger.LogInformation("Instance {InstanceName} deleted successfully.", instanceData.InstanceName); + } + catch (Exception ex) + { + _logger.LogError(ex, "Failed to delete instance: {InstanceName}", instanceData); + } + } + } + } + } +} diff --git a/Application/EdFi.Ods.AdminApi/Features/InstanceManagement/InstanceManagementTrigger.cs b/Application/EdFi.Ods.AdminApi/Features/InstanceManagement/InstanceManagementTrigger.cs new file mode 100644 index 000000000..06d225e52 --- /dev/null +++ b/Application/EdFi.Ods.AdminApi/Features/InstanceManagement/InstanceManagementTrigger.cs @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: Apache-2.0 +// Licensed to the Ed-Fi Alliance under one or more agreements. +// The Ed-Fi Alliance licenses this file to you under the Apache License, Version 2.0. +// See the LICENSE and NOTICES files in the project root for more information. + +using EdFi.Ods.AdminApi.Common.Features; +using EdFi.Ods.AdminApi.Common.Infrastructure; +using EdFi.Ods.AdminApi.Infrastructure.BackgroundJobs; +using Quartz; + +namespace EdFi.Ods.AdminApi.Features.InstanceManagement; + +public class InstanceManagementTrigger : IFeature +{ + public void MapEndpoints(IEndpointRouteBuilder endpoints) + { + var config = endpoints.ServiceProvider.GetRequiredService(); + bool enabled = config.GetValue("AppSettings:EnableAdminConsoleAPI"); + if (enabled) + { + AdminApiEndpointBuilder.MapPost(endpoints, "/instancemanagement/trigger", TriggerHealthCheck) + .WithRouteOptions(b => b.WithResponseCode(202)) + .AllowAnonymous() + .BuildForVersions(AdminApiVersions.AdminConsole); + } + } + + internal static async Task TriggerHealthCheck(ISchedulerFactory schedulerFactory) + { + var scheduler = await schedulerFactory.GetScheduler(); + var jobKey = new JobKey("InstanceManagementJob"); + + if (!await scheduler.CheckExists(jobKey)) + { + var jobDetail = JobBuilder.Create() + .WithIdentity(jobKey) + .Build(); + await scheduler.AddJob(jobDetail, replace: true); + } + + // Fire-and-forget: schedule a one-time immediate trigger + var trigger = TriggerBuilder.Create() + .ForJob(jobKey) + .WithIdentity($"ImmediateTrigger-{Guid.NewGuid()}") + .StartNow() + .Build(); + + await scheduler.ScheduleJob(trigger); + + // Return accepted immediately without waiting for execution + return Results.Accepted("/instancemanagement/trigger", new { Title = "Instance Management process accepted and triggered. The latest results will be available shortly, and processing details will be logged for your reference.", Status = 202 }); + } +} diff --git a/Application/EdFi.Ods.AdminApi/Features/RequestLoggingMiddleware.cs b/Application/EdFi.Ods.AdminApi/Features/RequestLoggingMiddleware.cs index f76f377ec..5adc58071 100644 --- a/Application/EdFi.Ods.AdminApi/Features/RequestLoggingMiddleware.cs +++ b/Application/EdFi.Ods.AdminApi/Features/RequestLoggingMiddleware.cs @@ -3,11 +3,11 @@ // The Ed-Fi Alliance licenses this file to you under the Apache License, Version 2.0. // See the LICENSE and NOTICES files in the project root for more information. -using EdFi.Common.Utils.Extensions; -using EdFi.Ods.AdminApi.Common.Infrastructure.ErrorHandling; -using FluentValidation; using System.Net; using System.Text.Json; +using EdFi.Ods.AdminApi.Common.Infrastructure.ErrorHandling; +using EdFi.Ods.Common.Utils.Extensions; +using FluentValidation; namespace EdFi.Ods.AdminApi.Features; diff --git a/Application/EdFi.Ods.AdminApi/Infrastructure/BackgroundJobs/InstanceManagementJob.cs b/Application/EdFi.Ods.AdminApi/Infrastructure/BackgroundJobs/InstanceManagementJob.cs new file mode 100644 index 000000000..9d6b5754d --- /dev/null +++ b/Application/EdFi.Ods.AdminApi/Infrastructure/BackgroundJobs/InstanceManagementJob.cs @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: Apache-2.0 +// Licensed to the Ed-Fi Alliance under one or more agreements. +// The Ed-Fi Alliance licenses this file to you under the Apache License, Version 2.0. +// See the LICENSE and NOTICES files in the project root for more information. + +using EdFi.Ods.AdminApi.Features.InstanceManagement; +using Quartz; + +namespace EdFi.Ods.AdminApi.Infrastructure.BackgroundJobs; + +[DisallowConcurrentExecution] +public class InstanceManagementJob(IInstanceManagementService instanceManagementService, ILogger logger) : IJob +{ + private readonly IInstanceManagementService _instanceManagementService = instanceManagementService; + private readonly ILogger _logger = logger; + + public async Task Execute(IJobExecutionContext context) + { + _logger.LogInformation("Running scheduled instance management..."); + await _instanceManagementService.RunAsync(context.CancellationToken); + } +} diff --git a/Application/EdFi.Ods.AdminApi/Infrastructure/BackgroundJobs/InstanceManagementServiceExtension.cs b/Application/EdFi.Ods.AdminApi/Infrastructure/BackgroundJobs/InstanceManagementServiceExtension.cs new file mode 100644 index 000000000..0a1909090 --- /dev/null +++ b/Application/EdFi.Ods.AdminApi/Infrastructure/BackgroundJobs/InstanceManagementServiceExtension.cs @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: Apache-2.0 +// Licensed to the Ed-Fi Alliance under one or more agreements. +// The Ed-Fi Alliance licenses this file to you under the Apache License, Version 2.0. +// See the LICENSE and NOTICES files in the project root for more information. + +using EdFi.AdminConsole.InstanceMgrWorker.Configuration.Provisioners; +using EdFi.Ods.AdminApi.Common.Infrastructure; +using EdFi.Ods.AdminApi.Common.Settings; +using EdFi.Ods.AdminApi.Features.InstanceManagement; +using EdFi.Ods.Common.Configuration; +using EdFi.Ods.Common.Database; + +namespace EdFi.Ods.AdminApi.Infrastructure.BackgroundJobs; + +public static class InstanceManagementServiceExtension +{ + public static void ConfigureInstanceManagementServices( + this WebApplicationBuilder builder, + IConfiguration configuration + ) + { + builder.Services.AddOptions(); + builder.Services.Configure(configuration.GetSection("AppSettings")); + builder.Services.AddLogging(configure => configure.AddConsole()); +#pragma warning disable CS8603 // Possible null reference return. + builder.Services.AddSingleton(sp => sp.GetService>()); +#pragma warning restore CS8603 // Possible null reference return. + builder.Services.AddTransient(); + builder.Services.AddTransient(); + builder.Services.AddTransient(); + builder.Services.AddTransient(); + + var isSqlServer = DatabaseEngineEnum.Parse( + configuration.GetValue("AppSettings:DatabaseEngine") ?? DatabaseEngineEnum.SqlServer.ToString() + ) == DatabaseEngineEnum.SqlServer; + + if (isSqlServer) + { + builder.Services.AddTransient(); + builder.Services.AddTransient(); + } + else + { + builder.Services.AddTransient(); + builder.Services.AddTransient(); + } + } +} diff --git a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetApiClientsByApplicationIdQuery.cs b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetApiClientsByApplicationIdQuery.cs index e085133fc..378c47a63 100644 --- a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetApiClientsByApplicationIdQuery.cs +++ b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetApiClientsByApplicationIdQuery.cs @@ -5,8 +5,7 @@ using EdFi.Admin.DataAccess.Contexts; using EdFi.Admin.DataAccess.Models; -using EdFi.Common.Extensions; -using EdFi.Ods.AdminApi.Common.Infrastructure.ErrorHandling; +using EdFi.Ods.Common.Extensions; using Microsoft.EntityFrameworkCore; namespace EdFi.Ods.AdminApi.Infrastructure.Database.Queries; diff --git a/Application/EdFi.Ods.AdminApi/Infrastructure/Documentation/SwaggerOptionalSchemaFilter.cs b/Application/EdFi.Ods.AdminApi/Infrastructure/Documentation/SwaggerOptionalSchemaFilter.cs index 802a6c839..fad8fc447 100644 --- a/Application/EdFi.Ods.AdminApi/Infrastructure/Documentation/SwaggerOptionalSchemaFilter.cs +++ b/Application/EdFi.Ods.AdminApi/Infrastructure/Documentation/SwaggerOptionalSchemaFilter.cs @@ -8,7 +8,7 @@ using Newtonsoft.Json; using Swashbuckle.AspNetCore.SwaggerGen; using System.Linq; -using EdFi.Common.Extensions; +using EdFi.Ods.Common.Extensions; namespace EdFi.Ods.AdminApi.Infrastructure.Documentation; diff --git a/Application/EdFi.Ods.AdminApi/Infrastructure/Services/SimpleGetRequest.cs b/Application/EdFi.Ods.AdminApi/Infrastructure/Services/SimpleGetRequest.cs index 53e04d051..ddaf2cb66 100644 --- a/Application/EdFi.Ods.AdminApi/Infrastructure/Services/SimpleGetRequest.cs +++ b/Application/EdFi.Ods.AdminApi/Infrastructure/Services/SimpleGetRequest.cs @@ -9,7 +9,7 @@ namespace EdFi.Ods.AdminApi.Infrastructure.Services; public interface ISimpleGetRequest { - public Task DownloadString(string address); + Task DownloadString(string address); } public class SimpleGetRequest : ISimpleGetRequest diff --git a/Application/EdFi.Ods.AdminApi/Infrastructure/WebApplicationBuilderExtensions.cs b/Application/EdFi.Ods.AdminApi/Infrastructure/WebApplicationBuilderExtensions.cs index fdaa4999f..b348f180f 100644 --- a/Application/EdFi.Ods.AdminApi/Infrastructure/WebApplicationBuilderExtensions.cs +++ b/Application/EdFi.Ods.AdminApi/Infrastructure/WebApplicationBuilderExtensions.cs @@ -7,20 +7,22 @@ using System.Reflection; using System.Threading.RateLimiting; using EdFi.Admin.DataAccess.Contexts; -using EdFi.Common.Extensions; using EdFi.Ods.AdminApi.Common.Infrastructure; using EdFi.Ods.AdminApi.Common.Infrastructure.Context; using EdFi.Ods.AdminApi.Common.Infrastructure.Database; using EdFi.Ods.AdminApi.Common.Infrastructure.Extensions; using EdFi.Ods.AdminApi.Common.Infrastructure.MultiTenancy; -using EdFi.Ods.AdminApi.Common.Infrastructure.Providers.Interfaces; using EdFi.Ods.AdminApi.Common.Infrastructure.Providers; +using EdFi.Ods.AdminApi.Common.Infrastructure.Providers.Interfaces; using EdFi.Ods.AdminApi.Common.Infrastructure.Security; using EdFi.Ods.AdminApi.Common.Settings; using EdFi.Ods.AdminApi.Infrastructure.Api; +using EdFi.Ods.AdminApi.Infrastructure.BackgroundJobs; +using EdFi.Ods.AdminApi.Infrastructure.Database.Queries; using EdFi.Ods.AdminApi.Infrastructure.Documentation; using EdFi.Ods.AdminApi.Infrastructure.Security; using EdFi.Ods.AdminApi.Infrastructure.Services; +using EdFi.Ods.Common.Extensions; using EdFi.Security.DataAccess.Contexts; using FluentValidation; using FluentValidation.AspNetCore; @@ -29,7 +31,7 @@ using Microsoft.EntityFrameworkCore; using Microsoft.Net.Http.Headers; using Microsoft.OpenApi.Models; -using EdFi.Ods.AdminApi.Infrastructure.Database.Queries; +using Quartz; namespace EdFi.Ods.AdminApi.Infrastructure; @@ -215,6 +217,27 @@ public static void AddServices(this WebApplicationBuilder webApplicationBuilder) webApplicationBuilder.Services.AddHttpClient(); webApplicationBuilder.Services.AddTransient(); webApplicationBuilder.Services.AddTransient(); + + var adminConsoleIsEnabled = webApplicationBuilder.Configuration.GetValue("AppSettings:EnableAdminConsoleAPI"); + var instanceManagementFrequency = webApplicationBuilder.Configuration.GetValue("AppSettings:InstanceManagementFrequencyInMinutes"); + + if (adminConsoleIsEnabled) + { + // Quartz.NET back end service + webApplicationBuilder.Services.AddQuartz(q => + { + var jobKey = new JobKey("InstanceManagementJob"); + q.AddJob(opts => opts.WithIdentity(jobKey)); + + // Create a trigger that fires every 10 minutes + q.AddTrigger(opts => + opts.ForJob(jobKey) + .WithIdentity("InstanceManagementJob-trigger") + .WithSimpleSchedule(x => x.WithInterval(TimeSpan.FromMinutes(instanceManagementFrequency)).RepeatForever()) + ); + }); + webApplicationBuilder.Services.AddQuartzHostedService(q => q.WaitForJobsToComplete = false); + } } private static void EnableMultiTenancySupport(this WebApplicationBuilder webApplicationBuilder) @@ -427,7 +450,12 @@ public static void ConfigureRateLimiting(WebApplicationBuilder builder) var parts = rule.Endpoint.Split(':'); // Only support fixed window for now, parse period (e.g., "1m") var window = rule.Period.EndsWith('m') ? TimeSpan.FromMinutes(int.Parse(rule.Period.TrimEnd('m'))) : TimeSpan.FromMinutes(1); - if (path != null && parts.Length == 2 && method.Equals(parts[0], StringComparison.OrdinalIgnoreCase) && path.Equals(parts[1], StringComparison.OrdinalIgnoreCase)) + if ( + path != null + && parts.Length == 2 + && method.Equals(parts[0], StringComparison.OrdinalIgnoreCase) + && path.Equals(parts[1], StringComparison.OrdinalIgnoreCase) + ) { return RateLimitPartition.GetFixedWindowLimiter(rule.Endpoint, _ => new FixedWindowRateLimiterOptions { diff --git a/Application/EdFi.Ods.AdminApi/Program.cs b/Application/EdFi.Ods.AdminApi/Program.cs index f33fd09dd..7224c647e 100644 --- a/Application/EdFi.Ods.AdminApi/Program.cs +++ b/Application/EdFi.Ods.AdminApi/Program.cs @@ -9,6 +9,7 @@ using EdFi.Ods.AdminApi.Common.Infrastructure.MultiTenancy; using EdFi.Ods.AdminApi.Features; using EdFi.Ods.AdminApi.Infrastructure; +using EdFi.Ods.AdminApi.Infrastructure.BackgroundJobs; using log4net; var builder = WebApplication.CreateBuilder(args); @@ -25,7 +26,10 @@ builder.AddServices(); if (adminConsoleIsEnabled) +{ builder.RegisterAdminConsoleDependencies(); + builder.ConfigureInstanceManagementServices(builder.Configuration); +} var app = builder.Build(); diff --git a/Application/EdFi.Ods.AdminApi/appsettings.json b/Application/EdFi.Ods.AdminApi/appsettings.json index c17dadb7d..60cb474b5 100644 --- a/Application/EdFi.Ods.AdminApi/appsettings.json +++ b/Application/EdFi.Ods.AdminApi/appsettings.json @@ -9,7 +9,9 @@ "PreventDuplicateApplications": false, "EnableAdminConsoleAPI": false, "IgnoresCertificateErrors": false, - "EnableApplicationResetEndpoint": true + "EnableApplicationResetEndpoint": true, + "InstanceManagementFrequencyInMinutes": 10, + "SqlServerBakFile": "/tmp/Ods_Minimal_Template.bak" }, "AdminConsoleSettings": { "ApplicationName": "Ed-Fi Health Check", @@ -42,6 +44,8 @@ "EdFi_Admin": "Data Source=.\\;Initial Catalog=EdFi_Admin;Integrated Security=True", "EdFi_Security": "Data Source=.\\;Initial Catalog=EdFi_Security;Integrated Security=True" }, + "DatabaseProvider": "Npgsql", + "connectionStringsProvider": "Npgsql", "EdFiApiDiscoveryUrl": "https://api.ed-fi.org/v7.2/api/", "Log4NetCore": { "Log4NetConfigFileName": "log4net\\log4net.config" diff --git a/Application/EdFi.Ods.AdminConsole.DBTests/EdFi.Ods.AdminConsole.DBTests.csproj b/Application/EdFi.Ods.AdminConsole.DBTests/EdFi.Ods.AdminConsole.DBTests.csproj index a0388e639..2b649a9a3 100644 --- a/Application/EdFi.Ods.AdminConsole.DBTests/EdFi.Ods.AdminConsole.DBTests.csproj +++ b/Application/EdFi.Ods.AdminConsole.DBTests/EdFi.Ods.AdminConsole.DBTests.csproj @@ -37,4 +37,7 @@ Always + + + \ No newline at end of file diff --git a/Application/EdFi.Ods.AdminConsole.DBTests/Testing.cs b/Application/EdFi.Ods.AdminConsole.DBTests/Testing.cs index 47c4f7e7a..e2327cecf 100644 --- a/Application/EdFi.Ods.AdminConsole.DBTests/Testing.cs +++ b/Application/EdFi.Ods.AdminConsole.DBTests/Testing.cs @@ -46,7 +46,7 @@ public static IOptions GetAppSettings() return Options.Create(appSettings); } - public static IOptionsSnapshot GetOptionsSnapshot() + public static IOptionsMonitor GetOptionsSnapshot() { var appSettingsFile = new AppSettingsFile { @@ -100,8 +100,8 @@ public static IOptionsSnapshot GetOptionsSnapshot() } }; - var optionsSnapshot = A.Fake>(); - A.CallTo(() => optionsSnapshot.Value).Returns(appSettingsFile); + var optionsSnapshot = A.Fake>(); + A.CallTo(() => optionsSnapshot.CurrentValue).Returns(appSettingsFile); return optionsSnapshot; } diff --git a/Docker/Compose/mssql/MultiTenant/compose-build-binaries-multi-tenant.yml b/Docker/Compose/mssql/MultiTenant/compose-build-binaries-multi-tenant.yml index 54bd9b497..e1c9ae452 100644 --- a/Docker/Compose/mssql/MultiTenant/compose-build-binaries-multi-tenant.yml +++ b/Docker/Compose/mssql/MultiTenant/compose-build-binaries-multi-tenant.yml @@ -46,6 +46,8 @@ services: AdminConsoleSettings__CorsSettings__EnableCors: "${ENABLE_CORS:-false}" Authentication__IssuerUrl: ${ISSUER_URL} Authentication__SigningKey: ${SIGNING_KEY} + connectionStringsProvider: ${CONNECTION_STRINGS_PROVIDER:-SqlServer} + DatabaseProvider: ${DATABASEPROVIDER:-SqlServer} IpRateLimiting__EnableEndpointRateLimiting: ${IPRATELIMITING__ENABLEENDPOINTRATELIMITING:-false} IpRateLimiting__StackBlockedRequests: ${IPRATELIMITING__STACKBLOCKEDREQUESTS:-false} IpRateLimiting__RealIpHeader: ${IPRATELIMITING__REALIPHEADER:-X-Real-IP} diff --git a/Docker/Compose/mssql/MultiTenant/compose-build-dev-multi-tenant.yml b/Docker/Compose/mssql/MultiTenant/compose-build-dev-multi-tenant.yml index 0b2bb5182..b59560050 100644 --- a/Docker/Compose/mssql/MultiTenant/compose-build-dev-multi-tenant.yml +++ b/Docker/Compose/mssql/MultiTenant/compose-build-dev-multi-tenant.yml @@ -53,6 +53,8 @@ services: Authentication__AllowRegistration: true Authentication__IssuerUrl: ${ISSUER_URL} Authentication__SigningKey: ${SIGNING_KEY} + connectionStringsProvider: ${CONNECTION_STRINGS_PROVIDER:-SqlServer} + DatabaseProvider: ${DATABASEPROVIDER:-SqlServer} EnableDockerEnvironment: true IpRateLimiting__EnableEndpointRateLimiting: ${IPRATELIMITING__ENABLEENDPOINTRATELIMITING:-false} IpRateLimiting__StackBlockedRequests: ${IPRATELIMITING__STACKBLOCKEDREQUESTS:-false} diff --git a/Docker/Compose/mssql/MultiTenant/compose-build-idp-binaries-multi-tenant.yml b/Docker/Compose/mssql/MultiTenant/compose-build-idp-binaries-multi-tenant.yml index c4e101fbe..4b016cf07 100644 --- a/Docker/Compose/mssql/MultiTenant/compose-build-idp-binaries-multi-tenant.yml +++ b/Docker/Compose/mssql/MultiTenant/compose-build-idp-binaries-multi-tenant.yml @@ -48,6 +48,8 @@ services: ASPNETCORE_ENVIRONMENT: "multitenantdocker" Authentication__IssuerUrl: ${ISSUER_URL} Authentication__SigningKey: ${SIGNING_KEY} + connectionStringsProvider: ${CONNECTION_STRINGS_PROVIDER:-SqlServer} + DatabaseProvider: ${DATABASEPROVIDER:-SqlServer} IpRateLimiting__EnableEndpointRateLimiting: ${IPRATELIMITING__ENABLEENDPOINTRATELIMITING:-false} IpRateLimiting__StackBlockedRequests: ${IPRATELIMITING__STACKBLOCKEDREQUESTS:-false} IpRateLimiting__RealIpHeader: ${IPRATELIMITING__REALIPHEADER:-X-Real-IP} diff --git a/Docker/Compose/mssql/MultiTenant/compose-build-idp-dev-multi-tenant.yml b/Docker/Compose/mssql/MultiTenant/compose-build-idp-dev-multi-tenant.yml index 58d477911..75c090d43 100644 --- a/Docker/Compose/mssql/MultiTenant/compose-build-idp-dev-multi-tenant.yml +++ b/Docker/Compose/mssql/MultiTenant/compose-build-idp-dev-multi-tenant.yml @@ -53,6 +53,8 @@ services: Authentication__AllowRegistration: true Authentication__IssuerUrl: ${ISSUER_URL} Authentication__SigningKey: ${SIGNING_KEY} + connectionStringsProvider: ${CONNECTION_STRINGS_PROVIDER:-SqlServer} + DatabaseProvider: ${DATABASEPROVIDER:-SqlServer} EnableDockerEnvironment: true IpRateLimiting__EnableEndpointRateLimiting: ${IPRATELIMITING__ENABLEENDPOINTRATELIMITING:-false} IpRateLimiting__StackBlockedRequests: ${IPRATELIMITING__STACKBLOCKEDREQUESTS:-false} diff --git a/Docker/Compose/mssql/SingleTenant/compose-build-binaries.yml b/Docker/Compose/mssql/SingleTenant/compose-build-binaries.yml index a3df75f51..f7d21fba0 100644 --- a/Docker/Compose/mssql/SingleTenant/compose-build-binaries.yml +++ b/Docker/Compose/mssql/SingleTenant/compose-build-binaries.yml @@ -50,6 +50,8 @@ services: AdminConsoleSettings__CorsSettings__EnableCors: "${ENABLE_CORS:-false}" ConnectionStrings__EdFi_Admin: "Data Source=db-admin,1433;Initial Catalog=EdFi_Admin;User Id=$SQLSERVER_USER;Password=$SQLSERVER_PASSWORD; Integrated Security=False;Encrypt=false;TrustServerCertificate=true" ConnectionStrings__EdFi_Security: "Data Source=db-admin,1433;Initial Catalog=EdFi_Security;User Id=$SQLSERVER_USER;Password=$SQLSERVER_PASSWORD; Integrated Security=False;Encrypt=false;TrustServerCertificate=true" + connectionStringsProvider: ${CONNECTION_STRINGS_PROVIDER:-SqlServer} + DatabaseProvider: ${DATABASEPROVIDER:-SqlServer} EdFiApiDiscoveryUrl: "${EDFI_API_DISCOVERY_URL:-https://host.docker.internal/api/}" IpRateLimiting__EnableEndpointRateLimiting: ${IPRATELIMITING__ENABLEENDPOINTRATELIMITING:-false} IpRateLimiting__StackBlockedRequests: ${IPRATELIMITING__STACKBLOCKEDREQUESTS:-false} diff --git a/Docker/Compose/mssql/SingleTenant/compose-build-dev.yml b/Docker/Compose/mssql/SingleTenant/compose-build-dev.yml index 1888b9b52..c9fd06793 100644 --- a/Docker/Compose/mssql/SingleTenant/compose-build-dev.yml +++ b/Docker/Compose/mssql/SingleTenant/compose-build-dev.yml @@ -54,6 +54,8 @@ services: Authentication__SigningKey: ${SIGNING_KEY} ConnectionStrings__EdFi_Admin: "Data Source=db-admin,1433;Initial Catalog=EdFi_Admin;User Id=${SQLSERVER_USER};Password=${SQLSERVER_PASSWORD}; Integrated Security=False;Encrypt=false;TrustServerCertificate=true" ConnectionStrings__EdFi_Security: "Data Source=db-admin,1433;Initial Catalog=EdFi_Security;User Id=${SQLSERVER_USER};Password=${SQLSERVER_PASSWORD}; Integrated Security=False;Encrypt=false;TrustServerCertificate=true" + connectionStringsProvider: ${CONNECTION_STRINGS_PROVIDER:-SqlServer} + DatabaseProvider: ${DATABASEPROVIDER:-SqlServer} EdFiApiDiscoveryUrl: "${EDFI_API_DISCOVERY_URL:-https://host.docker.internal/api/}" EnableDockerEnvironment: true IpRateLimiting__EnableEndpointRateLimiting: ${IPRATELIMITING__ENABLEENDPOINTRATELIMITING:-false} diff --git a/Docker/Compose/mssql/SingleTenant/compose-build-idp-binaries.yml b/Docker/Compose/mssql/SingleTenant/compose-build-idp-binaries.yml index 5e0c52a3c..fd08304ff 100644 --- a/Docker/Compose/mssql/SingleTenant/compose-build-idp-binaries.yml +++ b/Docker/Compose/mssql/SingleTenant/compose-build-idp-binaries.yml @@ -52,6 +52,8 @@ services: Authentication__SigningKey: ${SIGNING_KEY} ConnectionStrings__EdFi_Admin: "Data Source=db-admin,1433;Initial Catalog=EdFi_Admin;User Id=$SQLSERVER_USER;Password=$SQLSERVER_PASSWORD; Integrated Security=False;Encrypt=false;TrustServerCertificate=true" ConnectionStrings__EdFi_Security: "Data Source=db-admin,1433;Initial Catalog=EdFi_Security;User Id=$SQLSERVER_USER;Password=$SQLSERVER_PASSWORD; Integrated Security=False;Encrypt=false;TrustServerCertificate=true" + connectionStringsProvider: ${CONNECTION_STRINGS_PROVIDER:-SqlServer} + DatabaseProvider: ${DATABASEPROVIDER:-SqlServer} EdFiApiDiscoveryUrl: "${EDFI_API_DISCOVERY_URL:-https://host.docker.internal/api/}" IpRateLimiting__EnableEndpointRateLimiting: ${IPRATELIMITING__ENABLEENDPOINTRATELIMITING:-false} IpRateLimiting__StackBlockedRequests: ${IPRATELIMITING__STACKBLOCKEDREQUESTS:-false} diff --git a/Docker/Compose/mssql/SingleTenant/compose-build-idp-dev.yml b/Docker/Compose/mssql/SingleTenant/compose-build-idp-dev.yml index 1e9653702..58358e7ba 100644 --- a/Docker/Compose/mssql/SingleTenant/compose-build-idp-dev.yml +++ b/Docker/Compose/mssql/SingleTenant/compose-build-idp-dev.yml @@ -56,6 +56,8 @@ services: Authentication__SigningKey: ${SIGNING_KEY} ConnectionStrings__EdFi_Admin: "Data Source=db-admin,1433;Initial Catalog=EdFi_Admin;User Id=${SQLSERVER_USER};Password=${SQLSERVER_PASSWORD}; Integrated Security=False;Encrypt=false;TrustServerCertificate=true" ConnectionStrings__EdFi_Security: "Data Source=db-admin,1433;Initial Catalog=EdFi_Security;User Id=${SQLSERVER_USER};Password=${SQLSERVER_PASSWORD}; Integrated Security=False;Encrypt=false;TrustServerCertificate=true" + connectionStringsProvider: ${CONNECTION_STRINGS_PROVIDER:-SqlServer} + DatabaseProvider: ${DATABASEPROVIDER:-SqlServer} EdFiApiDiscoveryUrl: "${EDFI_API_DISCOVERY_URL:-https://host.docker.internal/api/}" EnableDockerEnvironment: true IpRateLimiting__EnableEndpointRateLimiting: ${IPRATELIMITING__ENABLEENDPOINTRATELIMITING:-false} diff --git a/Docker/Compose/pgsql/MultiTenant/compose-build-binaries-multi-tenant.yml b/Docker/Compose/pgsql/MultiTenant/compose-build-binaries-multi-tenant.yml index a48845aa3..33a4ce00e 100644 --- a/Docker/Compose/pgsql/MultiTenant/compose-build-binaries-multi-tenant.yml +++ b/Docker/Compose/pgsql/MultiTenant/compose-build-binaries-multi-tenant.yml @@ -46,6 +46,8 @@ services: ASPNETCORE_ENVIRONMENT: "multitenantdocker" Authentication__IssuerUrl: ${ISSUER_URL} Authentication__SigningKey: ${SIGNING_KEY} + connectionStringsProvider: ${CONNECTION_STRINGS_PROVIDER:-Npgsql} + DatabaseProvider: ${DATABASEPROVIDER:-Npgsql} IpRateLimiting__EnableEndpointRateLimiting: ${IPRATELIMITING__ENABLEENDPOINTRATELIMITING:-false} IpRateLimiting__StackBlockedRequests: ${IPRATELIMITING__STACKBLOCKEDREQUESTS:-false} IpRateLimiting__RealIpHeader: ${IPRATELIMITING__REALIPHEADER:-X-Real-IP} diff --git a/Docker/Compose/pgsql/MultiTenant/compose-build-dev-multi-tenant.yml b/Docker/Compose/pgsql/MultiTenant/compose-build-dev-multi-tenant.yml index 2d161b32d..36b8e20d8 100644 --- a/Docker/Compose/pgsql/MultiTenant/compose-build-dev-multi-tenant.yml +++ b/Docker/Compose/pgsql/MultiTenant/compose-build-dev-multi-tenant.yml @@ -52,6 +52,8 @@ services: Authentication__AllowRegistration: true Authentication__IssuerUrl: ${ISSUER_URL} Authentication__SigningKey: ${SIGNING_KEY} + connectionStringsProvider: ${CONNECTION_STRINGS_PROVIDER:-Npgsql} + DatabaseProvider: ${DATABASEPROVIDER:-Npgsql} EnableDockerEnvironment: true IpRateLimiting__EnableEndpointRateLimiting: ${IPRATELIMITING__ENABLEENDPOINTRATELIMITING:-false} IpRateLimiting__StackBlockedRequests: ${IPRATELIMITING__STACKBLOCKEDREQUESTS:-false} diff --git a/Docker/Compose/pgsql/MultiTenant/compose-build-idp-binaries-multi-tenant.yml b/Docker/Compose/pgsql/MultiTenant/compose-build-idp-binaries-multi-tenant.yml index f913178fe..8707b7cb1 100644 --- a/Docker/Compose/pgsql/MultiTenant/compose-build-idp-binaries-multi-tenant.yml +++ b/Docker/Compose/pgsql/MultiTenant/compose-build-idp-binaries-multi-tenant.yml @@ -47,6 +47,8 @@ services: ASPNETCORE_ENVIRONMENT: "multitenantdocker" Authentication__IssuerUrl: ${ISSUER_URL} Authentication__SigningKey: ${SIGNING_KEY} + connectionStringsProvider: ${CONNECTION_STRINGS_PROVIDER:-Npgsql} + DatabaseProvider: ${DATABASEPROVIDER:-Npgsql} IpRateLimiting__EnableEndpointRateLimiting: ${IPRATELIMITING__ENABLEENDPOINTRATELIMITING:-false} IpRateLimiting__StackBlockedRequests: ${IPRATELIMITING__STACKBLOCKEDREQUESTS:-false} IpRateLimiting__RealIpHeader: ${IPRATELIMITING__REALIPHEADER:-X-Real-IP} diff --git a/Docker/Compose/pgsql/MultiTenant/compose-build-idp-dev-multi-tenant.yml b/Docker/Compose/pgsql/MultiTenant/compose-build-idp-dev-multi-tenant.yml index 40a8d7820..57cbfc34a 100644 --- a/Docker/Compose/pgsql/MultiTenant/compose-build-idp-dev-multi-tenant.yml +++ b/Docker/Compose/pgsql/MultiTenant/compose-build-idp-dev-multi-tenant.yml @@ -54,6 +54,8 @@ services: Authentication__AllowRegistration: true Authentication__IssuerUrl: ${ISSUER_URL} Authentication__SigningKey: ${SIGNING_KEY} + connectionStringsProvider: ${CONNECTION_STRINGS_PROVIDER:-Npgsql} + DatabaseProvider: ${DATABASEPROVIDER:-Npgsql} EnableDockerEnvironment: true IpRateLimiting__EnableEndpointRateLimiting: ${IPRATELIMITING__ENABLEENDPOINTRATELIMITING:-false} IpRateLimiting__StackBlockedRequests: ${IPRATELIMITING__STACKBLOCKEDREQUESTS:-false} diff --git a/Docker/Compose/pgsql/SingleTenant/compose-build-binaries.yml b/Docker/Compose/pgsql/SingleTenant/compose-build-binaries.yml index 7252c4d10..99102caaf 100644 --- a/Docker/Compose/pgsql/SingleTenant/compose-build-binaries.yml +++ b/Docker/Compose/pgsql/SingleTenant/compose-build-binaries.yml @@ -48,6 +48,8 @@ services: AdminConsoleSettings__CorsSettings__EnableCors: "${ENABLE_CORS:-false}" ConnectionStrings__EdFi_Admin: "host=pb-admin;port=${POSTGRES_PORT};username=${POSTGRES_USER};password=${POSTGRES_PASSWORD};database=EdFi_Admin;pooling=false" ConnectionStrings__EdFi_Security: "host=pb-admin;port=${POSTGRES_PORT};username=${POSTGRES_USER};password=${POSTGRES_PASSWORD};database=EdFi_Security;pooling=false" + connectionStringsProvider: ${CONNECTION_STRINGS_PROVIDER:-Npgsql} + DatabaseProvider: ${DATABASEPROVIDER:-Npgsql} EdFiApiDiscoveryUrl: "${EDFI_API_DISCOVERY_URL:-https://host.docker.internal/api/}" IpRateLimiting__EnableEndpointRateLimiting: ${IPRATELIMITING__ENABLEENDPOINTRATELIMITING:-false} IpRateLimiting__StackBlockedRequests: ${IPRATELIMITING__STACKBLOCKEDREQUESTS:-false} diff --git a/Docker/Compose/pgsql/SingleTenant/compose-build-dev.yml b/Docker/Compose/pgsql/SingleTenant/compose-build-dev.yml index 96a62b1f0..36b843e2e 100644 --- a/Docker/Compose/pgsql/SingleTenant/compose-build-dev.yml +++ b/Docker/Compose/pgsql/SingleTenant/compose-build-dev.yml @@ -50,6 +50,8 @@ services: Authentication__SigningKey: ${SIGNING_KEY} ConnectionStrings__EdFi_Admin: "host=pb-admin;port=${PGBOUNCER_LISTEN_PORT:-6432};username=${POSTGRES_USER};password=${POSTGRES_PASSWORD};database=EdFi_Admin;pooling=false" ConnectionStrings__EdFi_Security: "host=pb-admin;port=${PGBOUNCER_LISTEN_PORT:-6432};username=${POSTGRES_USER};password=${POSTGRES_PASSWORD};database=EdFi_Security;pooling=false" + connectionStringsProvider: ${CONNECTION_STRINGS_PROVIDER:-Npgsql} + DatabaseProvider: ${DATABASEPROVIDER:-Npgsql} EdFiApiDiscoveryUrl: "${EDFI_API_DISCOVERY_URL:-https://host.docker.internal/api/}" EnableDockerEnvironment: true IpRateLimiting__EnableEndpointRateLimiting: ${IPRATELIMITING__ENABLEENDPOINTRATELIMITING:-false} diff --git a/Docker/Compose/pgsql/SingleTenant/compose-build-idp-binaries.yml b/Docker/Compose/pgsql/SingleTenant/compose-build-idp-binaries.yml index bd92661af..9a0f9e032 100644 --- a/Docker/Compose/pgsql/SingleTenant/compose-build-idp-binaries.yml +++ b/Docker/Compose/pgsql/SingleTenant/compose-build-idp-binaries.yml @@ -50,6 +50,8 @@ services: Authentication__SigningKey: ${SIGNING_KEY} ConnectionStrings__EdFi_Admin: "host=pb-admin;port=${POSTGRES_PORT};username=${POSTGRES_USER};password=${POSTGRES_PASSWORD};database=EdFi_Admin;pooling=false" ConnectionStrings__EdFi_Security: "host=pb-admin;port=${POSTGRES_PORT};username=${POSTGRES_USER};password=${POSTGRES_PASSWORD};database=EdFi_Security;pooling=false" + connectionStringsProvider: ${CONNECTION_STRINGS_PROVIDER:-Npgsql} + DatabaseProvider: ${DATABASEPROVIDER:-Npgsql} EdFiApiDiscoveryUrl: "${EDFI_API_DISCOVERY_URL:-https://host.docker.internal/api/}" IpRateLimiting__EnableEndpointRateLimiting: ${IPRATELIMITING__ENABLEENDPOINTRATELIMITING:-false} IpRateLimiting__StackBlockedRequests: ${IPRATELIMITING__STACKBLOCKEDREQUESTS:-false} diff --git a/Docker/Compose/pgsql/SingleTenant/compose-build-idp-dev.yml b/Docker/Compose/pgsql/SingleTenant/compose-build-idp-dev.yml index 5b5a15f5c..29816dda4 100644 --- a/Docker/Compose/pgsql/SingleTenant/compose-build-idp-dev.yml +++ b/Docker/Compose/pgsql/SingleTenant/compose-build-idp-dev.yml @@ -53,6 +53,8 @@ services: Authentication__SigningKey: ${SIGNING_KEY} ConnectionStrings__EdFi_Admin: "host=pb-admin;port=${POSTGRES_PORT};username=${POSTGRES_USER};password=${POSTGRES_PASSWORD};database=EdFi_Admin;pooling=false" ConnectionStrings__EdFi_Security: "host=pb-admin;port=${POSTGRES_PORT};username=${POSTGRES_USER};password=${POSTGRES_PASSWORD};database=EdFi_Security;pooling=false" + connectionStringsProvider: ${CONNECTION_STRINGS_PROVIDER:-Npgsql} + DatabaseProvider: ${DATABASEPROVIDER:-Npgsql} EdFiApiDiscoveryUrl: "${EDFI_API_DISCOVERY_URL:-https://host.docker.internal/api/}" EnableDockerEnvironment: true IpRateLimiting__EnableEndpointRateLimiting: ${IPRATELIMITING__ENABLEENDPOINTRATELIMITING:-false} diff --git a/Docker/dev.mssql.Dockerfile b/Docker/dev.mssql.Dockerfile index 27e78554a..1e5f9432d 100644 --- a/Docker/dev.mssql.Dockerfile +++ b/Docker/dev.mssql.Dockerfile @@ -24,6 +24,9 @@ COPY --from=assets ./Application/EdFi.Ods.AdminApi.AdminConsole EdFi.Ods.AdminAp COPY --from=assets ./Application/NuGet.Config EdFi.Ods.AdminApi.Common/ COPY --from=assets ./Application/EdFi.Ods.AdminApi.Common EdFi.Ods.AdminApi.Common/ +COPY --from=assets ./Application/NuGet.Config EdFi.AdminConsole.InstanceMgrWorker.Provisioner/ +COPY --from=assets ./Application/EdFi.AdminConsole.InstanceMgrWorker.Provisioner EdFi.AdminConsole.InstanceMgrWorker.Provisioner/ + WORKDIR /source/EdFi.Ods.AdminApi RUN export ASPNETCORE_ENVIRONMENT=$ASPNETCORE_ENVIRONMENT RUN dotnet restore && dotnet build -c Release diff --git a/Docker/dev.pgsql.Dockerfile b/Docker/dev.pgsql.Dockerfile index 34daa1f41..1eebcee4e 100644 --- a/Docker/dev.pgsql.Dockerfile +++ b/Docker/dev.pgsql.Dockerfile @@ -24,6 +24,9 @@ COPY --from=assets ./Application/EdFi.Ods.AdminApi.AdminConsole EdFi.Ods.AdminAp COPY --from=assets ./Application/NuGet.Config EdFi.Ods.AdminApi.Common/ COPY --from=assets ./Application/EdFi.Ods.AdminApi.Common EdFi.Ods.AdminApi.Common/ +COPY --from=assets ./Application/NuGet.Config EdFi.AdminConsole.InstanceMgrWorker.Provisioner/ +COPY --from=assets ./Application/EdFi.AdminConsole.InstanceMgrWorker.Provisioner EdFi.AdminConsole.InstanceMgrWorker.Provisioner/ + WORKDIR /source/EdFi.Ods.AdminApi RUN export ASPNETCORE_ENVIRONMENT=$ASPNETCORE_ENVIRONMENT RUN dotnet restore && dotnet build -c Release