Skip to content

Commit 7925bda

Browse files
committed
Merge branch 'main' into dmkorolev/formvalueproviderfactory
2 parents 1b98d04 + e849f20 commit 7925bda

File tree

12 files changed

+128
-22
lines changed

12 files changed

+128
-22
lines changed

.github/copilot-instructions.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
* Always use the latest version C#, currently C# 13 features.
55
* Never change global.json unless explicitly asked to.
66
* Never change package.json or package-lock.json files unless explicitly asked to.
7+
* Never change NuGet.config files unless explicitly asked to.
78

89
## Formatting
910

docs/DailyBuilds.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ Daily builds include the latest source code changes. They are not supported for
44

55
If you want to download the latest daily build and use it in a project, then you need to:
66

7-
* Obtain the latest [build of the .NET Core SDK](https://github.com/dotnet/sdk/blob/main/documentation/package-table.md).
7+
* Obtain the latest [build of the .NET Core SDK](https://github.com/dotnet/dotnet/blob/main/docs/builds-table.md).
88
* Add a NuGet.Config to your project directory with the following content:
99

1010
## .NET 8

global.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
{
22
"sdk": {
3-
"version": "10.0.100-preview.5.25265.106"
3+
"version": "10.0.100-preview.4.25216.37"
44
},
55
"tools": {
6-
"dotnet": "10.0.100-preview.5.25265.106",
6+
"dotnet": "10.0.100-preview.4.25216.37",
77
"runtimes": {
88
"dotnet/x86": [
99
"$(MicrosoftInternalRuntimeAspNetCoreTransportVersion)"

src/Http/Authentication.Abstractions/src/AuthenticationOptions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ public void AddScheme(string name, Action<AuthenticationSchemeBuilder> configure
9191
public string? DefaultForbidScheme { get; set; }
9292

9393
/// <summary>
94-
/// If true, SignIn should throw if attempted with a user is not authenticated.
94+
/// If true, SignIn should throw if attempted with a user who is not authenticated.
9595
/// A user is considered authenticated if <see cref="ClaimsIdentity.IsAuthenticated"/> returns <see langword="true" /> for the <see cref="ClaimsPrincipal"/> associated with the HTTP request.
9696
/// </summary>
9797
public bool RequireAuthenticatedSignIn { get; set; } = true;

src/OpenApi/src/Schemas/OpenApiJsonSchema.Helpers.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,8 @@ internal sealed partial class OpenApiJsonSchema
140140
{
141141
type = JsonSchemaType.Array;
142142
var array = new JsonArray();
143+
// Read to process JsonTokenType.StartArray before advancing
144+
reader.Read();
143145
while (reader.TokenType != JsonTokenType.EndArray)
144146
{
145147
array.Add(ReadJsonNode(ref reader));

src/OpenApi/test/Microsoft.AspNetCore.OpenApi.Tests/Services/OpenApiSchemaService/OpenApiSchemaService.ParameterSchemas.cs

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -722,4 +722,93 @@ public static bool TryParse(string value, out Student result)
722722
return true;
723723
}
724724
}
725+
726+
// Regression test for https://github.com/dotnet/aspnetcore/issues/62023
727+
// Testing that the array parsing in our OpenApiJsonSchema works
728+
[Fact]
729+
public async Task CustomConverterThatOutputsArrayWithDefaultValue()
730+
{
731+
// Arrange
732+
var serviceCollection = new ServiceCollection();
733+
serviceCollection.ConfigureHttpJsonOptions(options =>
734+
{
735+
options.SerializerOptions.Converters.Add(new EnumArrayTypeConverter());
736+
});
737+
var builder = CreateBuilder(serviceCollection);
738+
739+
// Act
740+
builder.MapPost("/api", (EnumArrayType e = EnumArrayType.None) => { });
741+
742+
// Assert
743+
await VerifyOpenApiDocument(builder, document =>
744+
{
745+
var operation = document.Paths["/api"].Operations[HttpMethod.Post];
746+
var param = Assert.Single(operation.Parameters);
747+
Assert.NotNull(param.Schema);
748+
Assert.IsType<JsonArray>(param.Schema.Default);
749+
// Type is null, it's up to the user to configure this via a custom schema
750+
// transformer for types with a converter.
751+
Assert.Null(param.Schema.Type);
752+
});
753+
}
754+
755+
[Fact]
756+
public async Task CustomConverterThatOutputsObjectWithDefaultValue()
757+
{
758+
// Arrange
759+
var serviceCollection = new ServiceCollection();
760+
serviceCollection.ConfigureHttpJsonOptions(options =>
761+
{
762+
options.SerializerOptions.Converters.Add(new EnumObjectTypeConverter());
763+
});
764+
var builder = CreateBuilder(serviceCollection);
765+
766+
// Act
767+
builder.MapPost("/api", (EnumArrayType e = EnumArrayType.None) => { });
768+
769+
// Assert
770+
await VerifyOpenApiDocument(builder, document =>
771+
{
772+
var operation = document.Paths["/api"].Operations[HttpMethod.Post];
773+
var param = Assert.Single(operation.Parameters);
774+
Assert.NotNull(param.Schema);
775+
Assert.IsType<JsonObject>(param.Schema.Default);
776+
// Type is null, it's up to the user to configure this via a custom schema
777+
// transformer for types with a converter.
778+
Assert.Null(param.Schema.Type);
779+
});
780+
}
781+
782+
public enum EnumArrayType
783+
{
784+
None = 1
785+
}
786+
787+
public class EnumArrayTypeConverter : JsonConverter<EnumArrayType>
788+
{
789+
public override EnumArrayType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
790+
{
791+
return new EnumArrayType();
792+
}
793+
794+
public override void Write(Utf8JsonWriter writer, EnumArrayType value, JsonSerializerOptions options)
795+
{
796+
writer.WriteStartArray();
797+
writer.WriteEndArray();
798+
}
799+
}
800+
801+
public class EnumObjectTypeConverter : JsonConverter<EnumArrayType>
802+
{
803+
public override EnumArrayType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
804+
{
805+
return new EnumArrayType();
806+
}
807+
808+
public override void Write(Utf8JsonWriter writer, EnumArrayType value, JsonSerializerOptions options)
809+
{
810+
writer.WriteStartObject();
811+
writer.WriteEndObject();
812+
}
813+
}
725814
}

src/ProjectTemplates/Web.ProjectTemplates/content/BlazorWeb-CSharp/BlazorWeb-CSharp/Components/Account/Pages/ExternalLogin.razor

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -72,12 +72,14 @@
7272
if (RemoteError is not null)
7373
{
7474
RedirectManager.RedirectToWithStatus("Account/Login", $"Error from external provider: {RemoteError}", HttpContext);
75+
return;
7576
}
7677

7778
var info = await SignInManager.GetExternalLoginInfoAsync();
7879
if (info is null)
7980
{
8081
RedirectManager.RedirectToWithStatus("Account/Login", "Error loading external login information.", HttpContext);
82+
return;
8183
}
8284

8385
externalLoginInfo = info;
@@ -118,6 +120,7 @@
118120
externalLoginInfo.Principal.Identity?.Name,
119121
externalLoginInfo.LoginProvider);
120122
RedirectManager.RedirectTo(ReturnUrl);
123+
return;
121124
}
122125
else if (result.IsLockedOut)
123126
{
@@ -168,13 +171,17 @@
168171
{
169172
RedirectManager.RedirectTo("Account/RegisterConfirmation", new() { ["email"] = Input.Email });
170173
}
171-
172-
await SignInManager.SignInAsync(user, isPersistent: false, externalLoginInfo.LoginProvider);
173-
RedirectManager.RedirectTo(ReturnUrl);
174+
else
175+
{
176+
await SignInManager.SignInAsync(user, isPersistent: false, externalLoginInfo.LoginProvider);
177+
RedirectManager.RedirectTo(ReturnUrl);
178+
}
174179
}
175180
}
176-
177-
message = $"Error: {string.Join(",", result.Errors.Select(error => error.Description))}";
181+
else
182+
{
183+
message = $"Error: {string.Join(",", result.Errors.Select(error => error.Description))}";
184+
}
178185
}
179186

180187
private ApplicationUser CreateUser()

src/ProjectTemplates/Web.ProjectTemplates/content/BlazorWeb-CSharp/BlazorWeb-CSharp/Components/Account/Pages/Manage/ExternalLogins.razor

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -123,9 +123,11 @@
123123
{
124124
RedirectManager.RedirectToCurrentPageWithStatus("Error: The external login was not removed.", HttpContext);
125125
}
126-
127-
await SignInManager.RefreshSignInAsync(user);
128-
RedirectManager.RedirectToCurrentPageWithStatus("The external login was removed.", HttpContext);
126+
else
127+
{
128+
await SignInManager.RefreshSignInAsync(user);
129+
RedirectManager.RedirectToCurrentPageWithStatus("The external login was removed.", HttpContext);
130+
}
129131
}
130132

131133
private async Task OnGetLinkLoginCallbackAsync()
@@ -145,14 +147,16 @@
145147
}
146148

147149
var result = await UserManager.AddLoginAsync(user, info);
148-
if (!result.Succeeded)
150+
if (result.Succeeded)
151+
{
152+
// Clear the existing external cookie to ensure a clean login process
153+
await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme);
154+
155+
RedirectManager.RedirectToCurrentPageWithStatus("The external login was added.", HttpContext);
156+
}
157+
else
149158
{
150159
RedirectManager.RedirectToCurrentPageWithStatus("Error: The external login was not added. External logins can only be associated with one account.", HttpContext);
151160
}
152-
153-
// Clear the existing external cookie to ensure a clean login process
154-
await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme);
155-
156-
RedirectManager.RedirectToCurrentPageWithStatus("The external login was added.", HttpContext);
157161
}
158162
}

src/ProjectTemplates/Web.ProjectTemplates/content/BlazorWeb-CSharp/BlazorWeb-CSharp/Components/Account/Pages/Manage/Index.razor

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@
7272
if (!setPhoneResult.Succeeded)
7373
{
7474
RedirectManager.RedirectToCurrentPageWithStatus("Error: Failed to set phone number.", HttpContext);
75+
return;
7576
}
7677
}
7778

src/ProjectTemplates/Web.ProjectTemplates/content/BlazorWeb-CSharp/BlazorWeb-CSharp/Components/Account/Pages/Manage/PersonalData.razor

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@
3737
if (user is null)
3838
{
3939
RedirectManager.RedirectToInvalidUser(UserManager, HttpContext);
40-
return;
4140
}
4241
}
4342
}

0 commit comments

Comments
 (0)