From fe87e6d4ce56cda59474763067b929d4d92fd146 Mon Sep 17 00:00:00 2001 From: Martin Costello Date: Tue, 21 May 2024 15:57:23 +0100 Subject: [PATCH] Fix exceptions generating default values (#2895) - Fix SwaggerGeneratorException if the type of a `[DefaultValue]` does not match the type of the property when using System.Text.Json for serialization to resolve #2885. - Fix schema generation of default values for nullable enums with System.Text.Json to resolve #2904. - Resolve some IDE refactoring suggestions. - Render the response if an integration test fails. --- Swashbuckle.AspNetCore.sln | 7 +++ .../NewtonsoftDataContractResolver.cs | 2 +- .../JsonSerializerDataContractResolver.cs | 21 ++++++--- .../SchemaGenerator/SchemaGenerator.cs | 47 +++++++++++++------ .../SwaggerIntegrationTests.cs | 18 +++++-- ...hbuckle.AspNetCore.IntegrationTests.csproj | 7 +-- .../NewtonsoftSchemaGeneratorTests.cs | 1 + .../JsonSerializerSchemaGeneratorTests.cs | 1 + .../Fixtures/TypeWithDefaultAttributes.cs | 3 ++ .../MvcWithNullable/MvcWithNullable.csproj | 20 ++++++++ test/WebSites/MvcWithNullable/Program.cs | 40 ++++++++++++++++ .../Properties/launchSettings.json | 41 ++++++++++++++++ .../appsettings.Development.json | 8 ++++ .../WebSites/MvcWithNullable/appsettings.json | 9 ++++ test/WebSites/WebApi/Program.cs | 7 ++- 15 files changed, 198 insertions(+), 34 deletions(-) create mode 100644 test/WebSites/MvcWithNullable/MvcWithNullable.csproj create mode 100644 test/WebSites/MvcWithNullable/Program.cs create mode 100644 test/WebSites/MvcWithNullable/Properties/launchSettings.json create mode 100644 test/WebSites/MvcWithNullable/appsettings.Development.json create mode 100644 test/WebSites/MvcWithNullable/appsettings.json diff --git a/Swashbuckle.AspNetCore.sln b/Swashbuckle.AspNetCore.sln index 7fcf8c3e97..98b1fc2db9 100644 --- a/Swashbuckle.AspNetCore.sln +++ b/Swashbuckle.AspNetCore.sln @@ -115,6 +115,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebApi.Aot", "test\WebSites EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MinimalAppWithHostedServices", "test\WebSites\MinimalAppWithHostedServices\MinimalAppWithHostedServices.csproj", "{D06A88E8-6F42-4F40-943A-E266C0AE6EC9}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MvcWithNullable", "test\WebSites\MvcWithNullable\MvcWithNullable.csproj", "{F88B6070-BE3C-45F9-978C-2ECBA9518C24}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -265,6 +267,10 @@ Global {D06A88E8-6F42-4F40-943A-E266C0AE6EC9}.Debug|Any CPU.Build.0 = Debug|Any CPU {D06A88E8-6F42-4F40-943A-E266C0AE6EC9}.Release|Any CPU.ActiveCfg = Release|Any CPU {D06A88E8-6F42-4F40-943A-E266C0AE6EC9}.Release|Any CPU.Build.0 = Release|Any CPU + {F88B6070-BE3C-45F9-978C-2ECBA9518C24}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F88B6070-BE3C-45F9-978C-2ECBA9518C24}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F88B6070-BE3C-45F9-978C-2ECBA9518C24}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F88B6070-BE3C-45F9-978C-2ECBA9518C24}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -309,6 +315,7 @@ Global {DE1D77F8-3916-4DEE-A57D-6DDC357F64C6} = {DB3F57FC-1472-4F03-B551-43394DA3C5EB} {07BB09CF-6C6F-4D00-A459-93586345C921} = {DB3F57FC-1472-4F03-B551-43394DA3C5EB} {D06A88E8-6F42-4F40-943A-E266C0AE6EC9} = {DB3F57FC-1472-4F03-B551-43394DA3C5EB} + {F88B6070-BE3C-45F9-978C-2ECBA9518C24} = {DB3F57FC-1472-4F03-B551-43394DA3C5EB} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {36FC6A67-247D-4149-8EDD-79FFD1A75F51} diff --git a/src/Swashbuckle.AspNetCore.Newtonsoft/SchemaGenerator/NewtonsoftDataContractResolver.cs b/src/Swashbuckle.AspNetCore.Newtonsoft/SchemaGenerator/NewtonsoftDataContractResolver.cs index b1ac8118eb..81875cc98c 100644 --- a/src/Swashbuckle.AspNetCore.Newtonsoft/SchemaGenerator/NewtonsoftDataContractResolver.cs +++ b/src/Swashbuckle.AspNetCore.Newtonsoft/SchemaGenerator/NewtonsoftDataContractResolver.cs @@ -143,7 +143,7 @@ private string JsonConverterFunc(object value) return JsonConvert.SerializeObject(value, _serializerSettings); } - private IEnumerable GetDataPropertiesFor(JsonObjectContract jsonObjectContract, out Type extensionDataType) + private List GetDataPropertiesFor(JsonObjectContract jsonObjectContract, out Type extensionDataType) { var dataProperties = new List(); diff --git a/src/Swashbuckle.AspNetCore.SwaggerGen/SchemaGenerator/JsonSerializerDataContractResolver.cs b/src/Swashbuckle.AspNetCore.SwaggerGen/SchemaGenerator/JsonSerializerDataContractResolver.cs index d9487dda95..9b0b7fdc8b 100644 --- a/src/Swashbuckle.AspNetCore.SwaggerGen/SchemaGenerator/JsonSerializerDataContractResolver.cs +++ b/src/Swashbuckle.AspNetCore.SwaggerGen/SchemaGenerator/JsonSerializerDataContractResolver.cs @@ -41,12 +41,19 @@ public DataContract GetDataContractForType(Type type) var enumValues = type.GetEnumValues(); // Test to determine if the serializer will treat as string - var serializeAsString = (enumValues.Length > 0) - && JsonConverterFunc(enumValues.GetValue(0), type).StartsWith("\""); + var serializeAsString = + enumValues.Length > 0 && +#if NET5_0_OR_GREATER + JsonConverterFunc(enumValues.GetValue(0), type).StartsWith('\"'); +#else + JsonConverterFunc(enumValues.GetValue(0), type).StartsWith("\""); +#endif + + var exampleType = serializeAsString ? + typeof(string) : + type.GetEnumUnderlyingType(); - primitiveTypeAndFormat = serializeAsString - ? PrimitiveTypesAndFormats[typeof(string)] - : PrimitiveTypesAndFormats[type.GetEnumUnderlyingType()]; + primitiveTypeAndFormat = PrimitiveTypesAndFormats[exampleType]; return DataContract.ForPrimitive( underlyingType: type, @@ -144,7 +151,7 @@ public bool IsSupportedCollection(Type type, out Type itemType) return false; } - private IEnumerable GetDataPropertiesFor(Type objectType, out Type extensionDataType) + private List GetDataPropertiesFor(Type objectType, out Type extensionDataType) { extensionDataType = null; @@ -177,7 +184,7 @@ private IEnumerable GetDataPropertiesFor(Type objectType, out Type return (property.IsPubliclyReadable() || property.IsPubliclyWritable()) && - !(property.GetIndexParameters().Any()) && + !(property.GetIndexParameters().Length > 0) && !(property.HasAttribute() && isIgnoredViaNet5Attribute) && !(property.HasAttribute()) && !(_serializerOptions.IgnoreReadOnlyProperties && !property.IsPubliclyWritable()); diff --git a/src/Swashbuckle.AspNetCore.SwaggerGen/SchemaGenerator/SchemaGenerator.cs b/src/Swashbuckle.AspNetCore.SwaggerGen/SchemaGenerator/SchemaGenerator.cs index 3ca1f7ddd0..55047933b9 100644 --- a/src/Swashbuckle.AspNetCore.SwaggerGen/SchemaGenerator/SchemaGenerator.cs +++ b/src/Swashbuckle.AspNetCore.SwaggerGen/SchemaGenerator/SchemaGenerator.cs @@ -10,6 +10,7 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.ApiExplorer; +using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Models; namespace Swashbuckle.AspNetCore.SwaggerGen @@ -55,7 +56,7 @@ private OpenApiSchema GenerateSchemaForMember( if (_generatorOptions.UseAllOfToExtendReferenceSchemas && schema.Reference != null) { - schema.AllOf = new[] { new OpenApiSchema { Reference = schema.Reference } }; + schema.AllOf = [new OpenApiSchema { Reference = schema.Reference }]; schema.Reference = null; } @@ -80,8 +81,7 @@ private OpenApiSchema GenerateSchemaForMember( var defaultValueAttribute = customAttributes.OfType().FirstOrDefault(); if (defaultValueAttribute != null) { - var defaultAsJson = dataContract.JsonConverter(defaultValueAttribute.Value); - schema.Default = OpenApiAnyFactory.CreateFromJson(defaultAsJson); + schema.Default = GenerateDefaultValue(dataContract, modelType, defaultValueAttribute.Value); } var obsoleteAttribute = customAttributes.OfType().FirstOrDefault(); @@ -90,8 +90,9 @@ private OpenApiSchema GenerateSchemaForMember( schema.Deprecated = true; } - // NullableAttribute behaves diffrently for Dictionaries - if (schema.AdditionalPropertiesAllowed && modelType.IsGenericType && modelType.GetGenericTypeDefinition() == typeof(Dictionary<,>)) + // NullableAttribute behaves differently for Dictionaries + if (schema.AdditionalPropertiesAllowed && modelType.IsGenericType && + modelType.GetGenericTypeDefinition() == typeof(Dictionary<,>)) { schema.AdditionalProperties.Nullable = !memberInfo.IsDictionaryValueNonNullable(); } @@ -118,7 +119,7 @@ private OpenApiSchema GenerateSchemaForParameter( if (_generatorOptions.UseAllOfToExtendReferenceSchemas && schema.Reference != null) { - schema.AllOf = new[] { new OpenApiSchema { Reference = schema.Reference } }; + schema.AllOf = [new OpenApiSchema { Reference = schema.Reference }]; schema.Reference = null; } @@ -132,8 +133,7 @@ private OpenApiSchema GenerateSchemaForParameter( if (defaultValue != null) { - var defaultAsJson = dataContract.JsonConverter(defaultValue); - schema.Default = OpenApiAnyFactory.CreateFromJson(defaultAsJson); + schema.Default = GenerateDefaultValue(dataContract, modelType, defaultValue); } schema.ApplyValidationAttributes(customAttributes); @@ -200,15 +200,15 @@ private OpenApiSchema GeneratePolymorphicSchema( }; } - private static readonly Type[] BinaryStringTypes = new[] - { + private static readonly Type[] BinaryStringTypes = + [ typeof(IFormFile), typeof(FileResult), typeof(System.IO.Stream), #if NETCOREAPP3_0_OR_GREATER typeof(System.IO.Pipelines.PipeReader), #endif - }; + ]; private OpenApiSchema GenerateConcreteSchema(DataContract dataContract, SchemaRepository schemaRepository) { @@ -277,7 +277,7 @@ private bool TryGetCustomTypeMapping(Type modelType, out Func sch || (modelType.IsConstructedGenericType && _generatorOptions.CustomTypeMappings.TryGetValue(modelType.GetGenericTypeDefinition(), out schemaFactory)); } - private OpenApiSchema CreatePrimitiveSchema(DataContract dataContract) + private static OpenApiSchema CreatePrimitiveSchema(DataContract dataContract) { var schema = new OpenApiSchema { @@ -292,7 +292,7 @@ private OpenApiSchema CreatePrimitiveSchema(DataContract dataContract) schema.Enum = dataContract.EnumValues .Select(value => JsonSerializer.Serialize(value)) .Distinct() - .Select(valueAsJson => OpenApiAnyFactory.CreateFromJson(valueAsJson)) + .Select(OpenApiAnyFactory.CreateFromJson) .ToList(); return schema; @@ -402,7 +402,7 @@ private OpenApiSchema CreateObjectSchema(DataContract dataContract, SchemaReposi foreach (var dataProperty in applicableDataProperties) { - var customAttributes = dataProperty.MemberInfo?.GetInlineAndMetadataAttributes() ?? Enumerable.Empty(); + var customAttributes = dataProperty.MemberInfo?.GetInlineAndMetadataAttributes() ?? []; if (_generatorOptions.IgnoreObsoleteProperties && customAttributes.OfType().Any()) continue; @@ -519,5 +519,24 @@ private void ApplyFilters( filter.Apply(schema, filterContext); } } + + private IOpenApiAny GenerateDefaultValue( + DataContract dataContract, + Type modelType, + object defaultValue) + { + // If the types do not match (e.g. a default which is an integer is specified for a double), + // attempt to coerce the default value to the correct type so that it can be serialized correctly. + // See https://github.com/domaindrivendev/Swashbuckle.AspNetCore/issues/2885 and + // https://github.com/domaindrivendev/Swashbuckle.AspNetCore/issues/2904. + var defaultValueType = defaultValue?.GetType(); + if (defaultValueType != null && defaultValueType != modelType) + { + dataContract = GetDataContractFor(defaultValueType); + } + + var defaultAsJson = dataContract.JsonConverter(defaultValue); + return OpenApiAnyFactory.CreateFromJson(defaultAsJson); + } } } diff --git a/test/Swashbuckle.AspNetCore.IntegrationTests/SwaggerIntegrationTests.cs b/test/Swashbuckle.AspNetCore.IntegrationTests/SwaggerIntegrationTests.cs index eb2fcfcc6a..1365214429 100644 --- a/test/Swashbuckle.AspNetCore.IntegrationTests/SwaggerIntegrationTests.cs +++ b/test/Swashbuckle.AspNetCore.IntegrationTests/SwaggerIntegrationTests.cs @@ -118,13 +118,21 @@ public async Task SwaggerMiddleware_CanBeConfiguredMultipleTimes( public async Task SwaggerEndpoint_ReturnsValidSwaggerJson_For_WebApi( string swaggerRequestUri) { - await SwaggerEndpointReturnsValidSwaggerJson(swaggerRequestUri); + await SwaggerEndpointReturnsValidSwaggerJson(swaggerRequestUri); + } + + [Theory] + [InlineData("/swagger/v1/swagger.json")] + public async Task SwaggerEndpoint_ReturnsValidSwaggerJson_For_Mvc( + string swaggerRequestUri) + { + await SwaggerEndpointReturnsValidSwaggerJson(swaggerRequestUri); } [Fact] public async Task TypesAreRenderedCorrectly() { - using var application = new TestApplication(); + using var application = new TestApplication(); using var client = application.CreateDefaultClient(); using var swaggerResponse = await client.GetFromJsonAsync("/swagger/v1/swagger.json"); @@ -153,7 +161,7 @@ public async Task TypesAreRenderedCorrectly() ]); } - private async Task SwaggerEndpointReturnsValidSwaggerJson(string swaggerRequestUri) + private static async Task SwaggerEndpointReturnsValidSwaggerJson(string swaggerRequestUri) where TEntryPoint : class { using var application = new TestApplication(); @@ -163,11 +171,11 @@ private async Task SwaggerEndpointReturnsValidSwaggerJson(string sw } #endif - private async Task AssertValidSwaggerJson(HttpClient client, string swaggerRequestUri) + private static async Task AssertValidSwaggerJson(HttpClient client, string swaggerRequestUri) { using var swaggerResponse = await client.GetAsync(swaggerRequestUri); - swaggerResponse.EnsureSuccessStatusCode(); + Assert.True(swaggerResponse.IsSuccessStatusCode, await swaggerResponse.Content.ReadAsStringAsync()); using var contentStream = await swaggerResponse.Content.ReadAsStreamAsync(); new OpenApiStreamReader().Read(contentStream, out OpenApiDiagnostic diagnostic); Assert.Empty(diagnostic.Errors); diff --git a/test/Swashbuckle.AspNetCore.IntegrationTests/Swashbuckle.AspNetCore.IntegrationTests.csproj b/test/Swashbuckle.AspNetCore.IntegrationTests/Swashbuckle.AspNetCore.IntegrationTests.csproj index 13a400f73a..d4e5ac45f8 100644 --- a/test/Swashbuckle.AspNetCore.IntegrationTests/Swashbuckle.AspNetCore.IntegrationTests.csproj +++ b/test/Swashbuckle.AspNetCore.IntegrationTests/Swashbuckle.AspNetCore.IntegrationTests.csproj @@ -1,4 +1,4 @@ - + $(MSBuildThisFileDirectory)..\..\src\Swashbuckle.AspNetCore.Swagger\Swashbuckle.AspNetCore.Swagger.snk @@ -23,10 +23,7 @@ - - - - + diff --git a/test/Swashbuckle.AspNetCore.Newtonsoft.Test/SchemaGenerator/NewtonsoftSchemaGeneratorTests.cs b/test/Swashbuckle.AspNetCore.Newtonsoft.Test/SchemaGenerator/NewtonsoftSchemaGeneratorTests.cs index 799026119e..518e5db3d2 100644 --- a/test/Swashbuckle.AspNetCore.Newtonsoft.Test/SchemaGenerator/NewtonsoftSchemaGeneratorTests.cs +++ b/test/Swashbuckle.AspNetCore.Newtonsoft.Test/SchemaGenerator/NewtonsoftSchemaGeneratorTests.cs @@ -269,6 +269,7 @@ public void GenerateSchema_SetsNullableFlag_IfPropertyIsReferenceOrNullableType( [InlineData(typeof(TypeWithDefaultAttributes), nameof(TypeWithDefaultAttributes.LongWithDefault), "9223372036854775807")] [InlineData(typeof(TypeWithDefaultAttributes), nameof(TypeWithDefaultAttributes.FloatWithDefault), "3.4028235E+38")] [InlineData(typeof(TypeWithDefaultAttributes), nameof(TypeWithDefaultAttributes.DoubleWithDefault), "1.7976931348623157E+308")] + [InlineData(typeof(TypeWithDefaultAttributes), nameof(TypeWithDefaultAttributes.DoubleWithDefaultOfDifferentType), "1")] [InlineData(typeof(TypeWithDefaultAttributes), nameof(TypeWithDefaultAttributes.StringWithDefault), "\"foobar\"")] [InlineData(typeof(TypeWithDefaultAttributes), nameof(TypeWithDefaultAttributes.IntArrayWithDefault), "[\n 1,\n 2,\n 3\n]")] [InlineData(typeof(TypeWithDefaultAttributes), nameof(TypeWithDefaultAttributes.StringArrayWithDefault), "[\n \"foo\",\n \"bar\"\n]")] diff --git a/test/Swashbuckle.AspNetCore.SwaggerGen.Test/SchemaGenerator/JsonSerializerSchemaGeneratorTests.cs b/test/Swashbuckle.AspNetCore.SwaggerGen.Test/SchemaGenerator/JsonSerializerSchemaGeneratorTests.cs index 6416652ee9..d162753253 100644 --- a/test/Swashbuckle.AspNetCore.SwaggerGen.Test/SchemaGenerator/JsonSerializerSchemaGeneratorTests.cs +++ b/test/Swashbuckle.AspNetCore.SwaggerGen.Test/SchemaGenerator/JsonSerializerSchemaGeneratorTests.cs @@ -292,6 +292,7 @@ public void GenerateSchema_SetsNullableFlag_IfPropertyIsReferenceOrNullableType( [InlineData(typeof(TypeWithDefaultAttributes), nameof(TypeWithDefaultAttributes.LongWithDefault), "9223372036854775807")] [InlineData(typeof(TypeWithDefaultAttributes), nameof(TypeWithDefaultAttributes.FloatWithDefault), "3.4028235E+38")] [InlineData(typeof(TypeWithDefaultAttributes), nameof(TypeWithDefaultAttributes.DoubleWithDefault), "1.7976931348623157E+308")] + [InlineData(typeof(TypeWithDefaultAttributes), nameof(TypeWithDefaultAttributes.DoubleWithDefaultOfDifferentType), "1")] [InlineData(typeof(TypeWithDefaultAttributes), nameof(TypeWithDefaultAttributes.StringWithDefault), "\"foobar\"")] [InlineData(typeof(TypeWithDefaultAttributes), nameof(TypeWithDefaultAttributes.IntArrayWithDefault), "[\n 1,\n 2,\n 3\n]")] [InlineData(typeof(TypeWithDefaultAttributes), nameof(TypeWithDefaultAttributes.StringArrayWithDefault), "[\n \"foo\",\n \"bar\"\n]")] diff --git a/test/Swashbuckle.AspNetCore.TestSupport/Fixtures/TypeWithDefaultAttributes.cs b/test/Swashbuckle.AspNetCore.TestSupport/Fixtures/TypeWithDefaultAttributes.cs index b999efd4d5..f1bdd58371 100644 --- a/test/Swashbuckle.AspNetCore.TestSupport/Fixtures/TypeWithDefaultAttributes.cs +++ b/test/Swashbuckle.AspNetCore.TestSupport/Fixtures/TypeWithDefaultAttributes.cs @@ -19,6 +19,9 @@ public class TypeWithDefaultAttributes [DefaultValue(double.MaxValue)] public double DoubleWithDefault { get; set; } + [DefaultValue(1)] // Repro for https://github.com/domaindrivendev/Swashbuckle.AspNetCore/issues/2885 + public double DoubleWithDefaultOfDifferentType { get; set; } + [DefaultValue("foobar")] public string StringWithDefault { get; set; } diff --git a/test/WebSites/MvcWithNullable/MvcWithNullable.csproj b/test/WebSites/MvcWithNullable/MvcWithNullable.csproj new file mode 100644 index 0000000000..29f5a084a3 --- /dev/null +++ b/test/WebSites/MvcWithNullable/MvcWithNullable.csproj @@ -0,0 +1,20 @@ + + + + enable + $(NoWarn);CA1050 + enable + WebApi + net8.0 + + + + + + + + + + + + diff --git a/test/WebSites/MvcWithNullable/Program.cs b/test/WebSites/MvcWithNullable/Program.cs new file mode 100644 index 0000000000..c3d808e394 --- /dev/null +++ b/test/WebSites/MvcWithNullable/Program.cs @@ -0,0 +1,40 @@ +using Microsoft.AspNetCore.Mvc; + +var builder = WebApplication.CreateBuilder(args); + +builder.Services.AddControllers(); + +builder.Services.AddEndpointsApiExplorer(); +builder.Services.AddSwaggerGen(options => +{ + options.UseAllOfToExtendReferenceSchemas(); +}); + +var app = builder.Build(); +app.UseHttpsRedirection(); + +if (app.Environment.IsDevelopment()) +{ + _ = app.UseSwagger(); + _ = app.UseSwaggerUI(); +} + +app.MapControllers(); + +app.Run(); + +[ApiController] +[Route("api/[controller]")] +public class EnumController : ControllerBase +{ + [HttpGet] + public IActionResult Get(LogLevel? logLevel = LogLevel.Error) => Ok(new { logLevel }); +} + +namespace MvcWithNullable +{ + public partial class Program + { + // Expose the Program class for use with WebApplicationFactory + } +} diff --git a/test/WebSites/MvcWithNullable/Properties/launchSettings.json b/test/WebSites/MvcWithNullable/Properties/launchSettings.json new file mode 100644 index 0000000000..82bdd832be --- /dev/null +++ b/test/WebSites/MvcWithNullable/Properties/launchSettings.json @@ -0,0 +1,41 @@ +{ + "$schema": "http://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:21394", + "sslPort": 44373 + } + }, + "profiles": { + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "http://localhost:5205", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "https": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "https://localhost:7175;http://localhost:5205", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/test/WebSites/MvcWithNullable/appsettings.Development.json b/test/WebSites/MvcWithNullable/appsettings.Development.json new file mode 100644 index 0000000000..0c208ae918 --- /dev/null +++ b/test/WebSites/MvcWithNullable/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/test/WebSites/MvcWithNullable/appsettings.json b/test/WebSites/MvcWithNullable/appsettings.json new file mode 100644 index 0000000000..10f68b8c8b --- /dev/null +++ b/test/WebSites/MvcWithNullable/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +} diff --git a/test/WebSites/WebApi/Program.cs b/test/WebSites/WebApi/Program.cs index 860b079886..dc5b28abe7 100644 --- a/test/WebSites/WebApi/Program.cs +++ b/test/WebSites/WebApi/Program.cs @@ -40,7 +40,10 @@ record WeatherForecast(DateOnly Date, int TemperatureC, string? Summary) public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); } -public partial class Program +namespace WebApi { - // Expose the Program class for use with WebApplicationFactory + public partial class Program + { + // Expose the Program class for use with WebApplicationFactory + } }