Skip to content

Commit 814beca

Browse files
csharpfritzCopilot
andcommitted
Fix shopping cart, login, and register in FreshWingtipToys
Issue 1 - Shopping Cart: TextBox component was missing @onchange handler, so TextChanged/OnTextChanged callbacks never fired. Added HandleChange method to TextBox.razor.cs that updates Text, triggers validation, and invokes both TextChanged and OnTextChanged callbacks. Wired @onchange to both <input> and <textarea> elements in TextBox.razor. Issue 2 - Login: SignInManager.PasswordSignInAsync cannot set cookies from a SignalR circuit (InteractiveServer mode). Replaced direct SignInManager call with navigation to a minimal API endpoint (/Account/PerformLogin) that runs in HTTP context where cookies work. Issue 3 - Register: Same SignalR cookie limitation. UserManager.CreateAsync works fine in SignalR (no cookies), but SignInManager.SignInAsync does not. After user creation, redirect to /Account/PerformRegisterSignIn endpoint that validates credentials and sets the auth cookie via HTTP. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 104c549 commit 814beca

5 files changed

Lines changed: 67 additions & 22 deletions

File tree

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,38 @@
11
using Microsoft.AspNetCore.Components;
22
using Microsoft.AspNetCore.Components.Web;
3-
using Microsoft.AspNetCore.Identity;
43

54
namespace WingtipToys.Account
65
{
76
public partial class Login : ComponentBase
87
{
9-
[Inject] private SignInManager<IdentityUser> SignInManager { get; set; } = default!;
108
[Inject] private NavigationManager Navigation { get; set; } = default!;
119

10+
[SupplyParameterFromQuery(Name = "error")]
11+
public string? ErrorParam { get; set; }
12+
1213
private string email = "";
1314
private string password = "";
1415
private string errorMessage = "";
1516

16-
private async Task HandleLogin(MouseEventArgs args)
17+
protected override void OnParametersSet()
18+
{
19+
if (!string.IsNullOrEmpty(ErrorParam))
20+
{
21+
errorMessage = ErrorParam;
22+
}
23+
}
24+
25+
private void HandleLogin(MouseEventArgs args)
1726
{
1827
if (string.IsNullOrWhiteSpace(email) || string.IsNullOrWhiteSpace(password))
1928
{
2029
errorMessage = "Email and password are required.";
2130
return;
2231
}
2332

24-
var result = await SignInManager.PasswordSignInAsync(email, password, isPersistent: false, lockoutOnFailure: false);
25-
26-
if (result.Succeeded)
27-
{
28-
Navigation.NavigateTo("/", forceLoad: true);
29-
}
30-
else if (result.IsLockedOut)
31-
{
32-
Navigation.NavigateTo("/Account/Lockout");
33-
}
34-
else
35-
{
36-
errorMessage = "Invalid login attempt.";
37-
}
33+
// Navigate to HTTP endpoint so SignInManager can set cookies via the HTTP response
34+
var loginUrl = $"/Account/PerformLogin?email={Uri.EscapeDataString(email)}&password={Uri.EscapeDataString(password)}";
35+
Navigation.NavigateTo(loginUrl, forceLoad: true);
3836
}
3937
}
4038
}

samples/FreshWingtipToys/Account/Register.razor.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ namespace WingtipToys.Account
77
public partial class Register : ComponentBase
88
{
99
[Inject] private UserManager<IdentityUser> UserManager { get; set; } = default!;
10-
[Inject] private SignInManager<IdentityUser> SignInManager { get; set; } = default!;
1110
[Inject] private NavigationManager Navigation { get; set; } = default!;
1211

1312
private string email = "";
@@ -34,8 +33,9 @@ private async Task HandleRegister(MouseEventArgs args)
3433

3534
if (result.Succeeded)
3635
{
37-
await SignInManager.SignInAsync(user, isPersistent: false);
38-
Navigation.NavigateTo("/", forceLoad: true);
36+
// Navigate to HTTP endpoint so SignInManager can set cookies via the HTTP response
37+
var signInUrl = $"/Account/PerformRegisterSignIn?email={Uri.EscapeDataString(email)}&password={Uri.EscapeDataString(password)}";
38+
Navigation.NavigateTo(signInUrl, forceLoad: true);
3939
}
4040
else
4141
{

samples/FreshWingtipToys/Program.cs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,4 +65,37 @@
6565
app.MapRazorComponents<WingtipToys.Components.App>()
6666
.AddInteractiveServerRenderMode();
6767

68+
// HTTP endpoint for login — SignInManager requires an active HTTP response to set cookies,
69+
// which is not available inside a SignalR circuit (InteractiveServer mode).
70+
app.MapGet("/Account/PerformLogin", async (
71+
string email,
72+
string password,
73+
SignInManager<IdentityUser> signInManager) =>
74+
{
75+
var result = await signInManager.PasswordSignInAsync(email, password,
76+
isPersistent: false, lockoutOnFailure: false);
77+
78+
if (result.Succeeded)
79+
return Results.Redirect("/");
80+
if (result.IsLockedOut)
81+
return Results.Redirect("/Account/Lockout");
82+
83+
return Results.Redirect("/Account/Login?error=" + Uri.EscapeDataString("Invalid login attempt."));
84+
});
85+
86+
// HTTP endpoint for post-registration sign-in
87+
app.MapGet("/Account/PerformRegisterSignIn", async (
88+
string email,
89+
string password,
90+
SignInManager<IdentityUser> signInManager) =>
91+
{
92+
var result = await signInManager.PasswordSignInAsync(email, password,
93+
isPersistent: false, lockoutOnFailure: false);
94+
95+
if (result.Succeeded)
96+
return Results.Redirect("/");
97+
98+
return Results.Redirect("/Account/Login");
99+
});
100+
68101
app.Run();

src/BlazorWebFormsComponents/TextBox.razor

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44
{
55
@if (TextMode == TextBoxMode.MultiLine)
66
{
7-
<textarea @attributes="CalculatedAttributes">@Text</textarea>
7+
<textarea @attributes="CalculatedAttributes" @onchange="HandleChange">@Text</textarea>
88
}
99
else
1010
{
11-
<input type="@CalculatedType" value="@Text" @attributes="CalculatedAttributes" />
11+
<input type="@CalculatedType" value="@Text" @attributes="CalculatedAttributes" @onchange="HandleChange" />
1212
}
1313
}

src/BlazorWebFormsComponents/TextBox.razor.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using Microsoft.AspNetCore.Components;
55
using System;
66
using System.Collections.Generic;
7+
using System.Threading.Tasks;
78

89
namespace BlazorWebFormsComponents
910
{
@@ -71,6 +72,19 @@ public partial class TextBox : BaseStyledComponent, ITextComponent
7172
_ => "text"
7273
};
7374

75+
private async Task HandleChange(ChangeEventArgs e)
76+
{
77+
Text = e.Value?.ToString() ?? string.Empty;
78+
79+
if (CausesValidation && Coordinator != null)
80+
{
81+
Coordinator.ValidateGroup(ValidationGroup);
82+
}
83+
84+
await TextChanged.InvokeAsync(Text);
85+
await OnTextChanged.InvokeAsync(e);
86+
}
87+
7488
internal Dictionary<string, object> CalculatedAttributes
7589
{
7690
get

0 commit comments

Comments
 (0)