C
C#14mo ago
Very Funny

Unable to Promote or Demote users

I have buttons to promote and demote user roles, however they are currently doing nothing.
c#
@if (user.IsAdmin)
{
<button class="btn btn-danger" @onclick="() => DemoteUser(user.UserId)">Demote</button>
}
else
{
<button class="btn btn-success" @onclick="() => PromoteUser(user.UserId)">Promote</button>
}
...

@code
{
public List<UserInfo> Users { get; set; } = new ();

protected override async Task OnInitializedAsync()
{
var users = await UserManager.Users.ToListAsync();
foreach (var user in users)
{
var roles = await UserManager.GetRolesAsync(user);
var userInfo = new UserInfo
{
UserId = user.Id,
Email = user.Email,
Roles = new List<string>(roles),
IsAdmin = roles.Contains("Admin")
};
Users.Add(userInfo);
}
}

private async Task PromoteUser(string userId)
{
var user = await UserManager.FindByIdAsync(userId);
await UserManager.AddToRoleAsync(user, "Admin");
await OnInitializedAsync();
}

private async Task DemoteUser(string userId)
{
var user = await UserManager.FindByIdAsync(userId);
await UserManager.RemoveFromRoleAsync(user, "Admin");
await OnInitializedAsync();
}
}
c#
@if (user.IsAdmin)
{
<button class="btn btn-danger" @onclick="() => DemoteUser(user.UserId)">Demote</button>
}
else
{
<button class="btn btn-success" @onclick="() => PromoteUser(user.UserId)">Promote</button>
}
...

@code
{
public List<UserInfo> Users { get; set; } = new ();

protected override async Task OnInitializedAsync()
{
var users = await UserManager.Users.ToListAsync();
foreach (var user in users)
{
var roles = await UserManager.GetRolesAsync(user);
var userInfo = new UserInfo
{
UserId = user.Id,
Email = user.Email,
Roles = new List<string>(roles),
IsAdmin = roles.Contains("Admin")
};
Users.Add(userInfo);
}
}

private async Task PromoteUser(string userId)
{
var user = await UserManager.FindByIdAsync(userId);
await UserManager.AddToRoleAsync(user, "Admin");
await OnInitializedAsync();
}

private async Task DemoteUser(string userId)
{
var user = await UserManager.FindByIdAsync(userId);
await UserManager.RemoveFromRoleAsync(user, "Admin");
await OnInitializedAsync();
}
}
83 Replies
JakenVeina
JakenVeina14mo ago
define "doing nothing"
Very Funny
Very FunnyOP14mo ago
it is not calling the function
JakenVeina
JakenVeina14mo ago
how do you know?
Very Funny
Very FunnyOP14mo ago
I added Console.WriteLine to the functions and got nothing back
JakenVeina
JakenVeina14mo ago
that proves nothing set a breakpoint
Very Funny
Very FunnyOP14mo ago
I did also do that, it never got triggered
JakenVeina
JakenVeina14mo ago
at the beginning?
Very Funny
Very FunnyOP14mo ago
at the start of the Promote and Demote functions
JakenVeina
JakenVeina14mo ago
how about OnInitializedAsync()?
Very Funny
Very FunnyOP14mo ago
Ill give it a shot, see how it goes aside from the breakpoint being triggered when I load the page, nothing else
JakenVeina
JakenVeina14mo ago
according to docs, your syntax is wrong
JakenVeina
JakenVeina14mo ago
ASP.NET Core Blazor event handling
Learn about Blazor's event handling features, including event argument types, event callbacks, and managing default browser events.
Very Funny
Very FunnyOP14mo ago
As in @onclick="() => DemoteUser(user.UserId)" to @onclick="@(() => DemoteUser(user.UserId))
JakenVeina
JakenVeina14mo ago
that is what the docs suggest, yes
Very Funny
Very FunnyOP14mo ago
It does nothing as in, it does not fix the problem. I had tried it earlier as wewll
JakenVeina
JakenVeina14mo ago
or @onclick="@((e, args) => DemoteUser(user.UserId))"
Very Funny
Very FunnyOP14mo ago
e args causes a build issue just using e also does not fix anything
JakenVeina
JakenVeina14mo ago
try just @onclick="OnButtonClick" with a new function with no args
Very Funny
Very FunnyOP14mo ago
I did try that
JakenVeina
JakenVeina14mo ago
does the function get called?
Very Funny
Very FunnyOP14mo ago
no
JakenVeina
JakenVeina14mo ago
let's see the whole file
Very Funny
Very FunnyOP14mo ago
c#
@page "/Admin/ManageAdmin"
@using Microsoft.AspNetCore.Authorization
@using BlazorApp9.Data
@using Microsoft.AspNetCore.Identity
@using Microsoft.EntityFrameworkCore

@inject UserManager<ApplicationUser> UserManager
@inject RoleManager<IdentityRole> RoleManager

@attribute [Authorize(Roles = "Admin")]

<h1>Manage Admin</h1>

@if (Users.Count > 0)
{
<table class="table">
<thead>
<tr>
<th>Email</th>
<th>Name</th>
<th>Roles</th>
<th>Is Admin</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var user in Users)
{
<tr>
<td>@user.Email</td>
<td>@user.UserName</td>
<td>@string.Join(", ", user.Roles)</td>
<td>@user.IsAdmin</td>
<td>
@if (user.IsAdmin)
{
<button class="btn btn-danger" @onclick="() => DemoteUser(user.UserId)">Demote</button>
}
else
{
<button class="btn btn-success" @onclick="() => PromoteUser(user.UserId)">Promote</button>
<button @onclick="Greet">ClickMe</button>
}
</td>
</tr>
}
</tbody>
</table>
}
else
{
<p>No users found</p>
}

@code
{
public List<UserInfo> Users { get; set; } = new ();

public void Greet()
{
Console.WriteLine("Greet");
}

protected override async Task OnInitializedAsync()
{
var users = await UserManager.Users.ToListAsync();
foreach (var user in users)
{
var roles = await UserManager.GetRolesAsync(user);
var userInfo = new UserInfo
{
UserId = user.Id,
UserName = user.UserName,
Email = user.Email,
Roles = new List<string>(roles),
IsAdmin = roles.Contains("Admin")
};
Users.Add(userInfo);
}
}

public async Task PromoteUser(string userId)
{
Console.WriteLine("PromoteUser");
var user = await UserManager.FindByIdAsync(userId);
await UserManager.AddToRoleAsync(user, "Admin");
await OnInitializedAsync();
}

public async Task DemoteUser(string userId)
{
Console.WriteLine("DemoteUser");
var user = await UserManager.FindByIdAsync(userId);
await UserManager.RemoveFromRoleAsync(user, "Admin");
await OnInitializedAsync();
}
}
c#
@page "/Admin/ManageAdmin"
@using Microsoft.AspNetCore.Authorization
@using BlazorApp9.Data
@using Microsoft.AspNetCore.Identity
@using Microsoft.EntityFrameworkCore

@inject UserManager<ApplicationUser> UserManager
@inject RoleManager<IdentityRole> RoleManager

@attribute [Authorize(Roles = "Admin")]

<h1>Manage Admin</h1>

@if (Users.Count > 0)
{
<table class="table">
<thead>
<tr>
<th>Email</th>
<th>Name</th>
<th>Roles</th>
<th>Is Admin</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var user in Users)
{
<tr>
<td>@user.Email</td>
<td>@user.UserName</td>
<td>@string.Join(", ", user.Roles)</td>
<td>@user.IsAdmin</td>
<td>
@if (user.IsAdmin)
{
<button class="btn btn-danger" @onclick="() => DemoteUser(user.UserId)">Demote</button>
}
else
{
<button class="btn btn-success" @onclick="() => PromoteUser(user.UserId)">Promote</button>
<button @onclick="Greet">ClickMe</button>
}
</td>
</tr>
}
</tbody>
</table>
}
else
{
<p>No users found</p>
}

@code
{
public List<UserInfo> Users { get; set; } = new ();

public void Greet()
{
Console.WriteLine("Greet");
}

protected override async Task OnInitializedAsync()
{
var users = await UserManager.Users.ToListAsync();
foreach (var user in users)
{
var roles = await UserManager.GetRolesAsync(user);
var userInfo = new UserInfo
{
UserId = user.Id,
UserName = user.UserName,
Email = user.Email,
Roles = new List<string>(roles),
IsAdmin = roles.Contains("Admin")
};
Users.Add(userInfo);
}
}

public async Task PromoteUser(string userId)
{
Console.WriteLine("PromoteUser");
var user = await UserManager.FindByIdAsync(userId);
await UserManager.AddToRoleAsync(user, "Admin");
await OnInitializedAsync();
}

public async Task DemoteUser(string userId)
{
Console.WriteLine("DemoteUser");
var user = await UserManager.FindByIdAsync(userId);
await UserManager.RemoveFromRoleAsync(user, "Admin");
await OnInitializedAsync();
}
}
This is the file
JakenVeina
JakenVeina14mo ago
add the following imports
@using System.Net.Http
@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Components.Authorization
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using Microsoft.JSInterop
@using System.Net.Http
@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Components.Authorization
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using Microsoft.JSInterop
Very Funny
Very FunnyOP14mo ago
I have them all except for @using Microsoft.AspNetCore.Authorization
JakenVeina
JakenVeina14mo ago
I mean no you don't except for Microsoft.AspNetCore.Authorization which you DO already have
Very Funny
Very FunnyOP14mo ago
This is what is in my _Imports.razor file
c#
@using System.Net.Http
@using System.Net.Http.Json
@using Microsoft.AspNetCore.Components.Authorization
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using static Microsoft.AspNetCore.Components.Web.RenderMode
@using Microsoft.AspNetCore.Components.Web.Virtualization
@using Microsoft.JSInterop
@using BlazorApp9
@using BlazorApp9.Client
@using BlazorApp9.Components
c#
@using System.Net.Http
@using System.Net.Http.Json
@using Microsoft.AspNetCore.Components.Authorization
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using static Microsoft.AspNetCore.Components.Web.RenderMode
@using Microsoft.AspNetCore.Components.Web.Virtualization
@using Microsoft.JSInterop
@using BlazorApp9
@using BlazorApp9.Client
@using BlazorApp9.Components
I have not modified this file at all
JakenVeina
JakenVeina14mo ago
add them to your component file, for good measure
Very Funny
Very FunnyOP14mo ago
Every single one of them come up as unusued
No description
JakenVeina
JakenVeina14mo ago
that's a lie at least it was last time I used blazor
Very Funny
Very FunnyOP14mo ago
Adding them to my @page "/Admin/ManageAdmin" did nothing
JakenVeina
JakenVeina14mo ago
k
Very Funny
Very FunnyOP14mo ago
The _Imports files deals with them
JakenVeina
JakenVeina14mo ago
yes, I know welp, I'm out of ideas go back to a fresh sample template that works and try and figure out what you're doing differently
Very Funny
Very FunnyOP14mo ago
The defualt Counter page works fine
JakenVeina
JakenVeina14mo ago
within this same app?
Very Funny
Very FunnyOP14mo ago
Not really, thats in the .Client app Though they share the same imports
JakenVeina
JakenVeina14mo ago
....and this isn't?
Very Funny
Very FunnyOP14mo ago
It is in my main one
Very Funny
Very FunnyOP14mo ago
No description
JakenVeina
JakenVeina14mo ago
what is that supposed to mean ?
Very Funny
Very FunnyOP14mo ago
see pic above
JakenVeina
JakenVeina14mo ago
so.... what? what is that supposed to tell me?
Very Funny
Very FunnyOP14mo ago
idk, the fact @onlick works in my application, but not in the webpage I want it to work in
JakenVeina
JakenVeina14mo ago
that makes no sense
Very Funny
Very FunnyOP14mo ago
what doesn't make sense?
JakenVeina
JakenVeina14mo ago
what is your definition of "application" and "webpage" cause those are the same thing
Very Funny
Very FunnyOP14mo ago
app is the project, webpage is the single page I am having issues with
JakenVeina
JakenVeina14mo ago
so it doesn't work in your application because the page is in your application
Very Funny
Very FunnyOP14mo ago
Sure, all I know is @onclick in Counter works in the .Client project, but does not work in my server project
JakenVeina
JakenVeina14mo ago
why do you have a server project? why are you putting client stuff in your server project? why is anything that's working in the client project relevant to what works in the server project?
go back to a fresh sample template that works and try and figure out what you're doing differently
Very Funny
Very FunnyOP14mo ago
this project is about as fresh as they come
JakenVeina
JakenVeina14mo ago
you've changed something
Very Funny
Very FunnyOP14mo ago
yeah, added external auth and users to the db nothing I have changed should even be close to whatever is affecting this haven't touched imports
JakenVeina
JakenVeina14mo ago
something is and it's something you changed or added
Very Funny
Very FunnyOP14mo ago
Aight, this is what I have changed in my Program.cs
c#
builder.Services.AddAuthentication(options =>
{
options.DefaultScheme = IdentityConstants.ApplicationScheme;
options.DefaultSignInScheme = IdentityConstants.ExternalScheme;
})
.AddGoogle(options =>
{
options.ClientId = "220592118819-si6nuv8hed3g9acl09isjr8cv319b2cm.apps.googleusercontent.com";
options.ClientSecret = "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";
})
.AddIdentityCookies();
c#
builder.Services.AddAuthentication(options =>
{
options.DefaultScheme = IdentityConstants.ApplicationScheme;
options.DefaultSignInScheme = IdentityConstants.ExternalScheme;
})
.AddGoogle(options =>
{
options.ClientId = "220592118819-si6nuv8hed3g9acl09isjr8cv319b2cm.apps.googleusercontent.com";
options.ClientSecret = "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";
})
.AddIdentityCookies();
Added google auth
c#
builder.Services.AddIdentityCore<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddRoles<IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddSignInManager()
.AddDefaultTokenProviders();
c#
builder.Services.AddIdentityCore<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddRoles<IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddSignInManager()
.AddDefaultTokenProviders();
added AddRoles<..>()
JakenVeina
JakenVeina14mo ago
start removing those things until your blazor code starts working
Very Funny
Very FunnyOP14mo ago
c#
using var scope = app.Services.CreateScope();
var roleManager = scope.ServiceProvider.GetRequiredService<RoleManager<IdentityRole>>();
var userManager = scope.ServiceProvider.GetRequiredService<UserManager<ApplicationUser>>();
var adminRole = await roleManager.FindByNameAsync("Admin");
if (adminRole == null)
{
adminRole = new IdentityRole("Admin");
await roleManager.CreateAsync(adminRole);
}

var adminUser = await userManager.FindByNameAsync("[email protected]");
if (adminUser == null)
{
adminUser = new ApplicationUser
{
UserName = "[email protected]",
Email = "[email protected]",
EmailConfirmed = true
};

await userManager.CreateAsync(adminUser, "Admin123!");
}

if (!await userManager.IsInRoleAsync(adminUser, "Admin"))
{
await userManager.AddToRoleAsync(adminUser, "Admin");
}

// add admin role to external google user [email protected]
var googleUser = await userManager.FindByNameAsync("[email protected]");
if (googleUser != null)
{
if (!await userManager.IsInRoleAsync(googleUser, "Admin"))
{
await userManager.AddToRoleAsync(googleUser, "Admin");
}
}
c#
using var scope = app.Services.CreateScope();
var roleManager = scope.ServiceProvider.GetRequiredService<RoleManager<IdentityRole>>();
var userManager = scope.ServiceProvider.GetRequiredService<UserManager<ApplicationUser>>();
var adminRole = await roleManager.FindByNameAsync("Admin");
if (adminRole == null)
{
adminRole = new IdentityRole("Admin");
await roleManager.CreateAsync(adminRole);
}

var adminUser = await userManager.FindByNameAsync("[email protected]");
if (adminUser == null)
{
adminUser = new ApplicationUser
{
UserName = "[email protected]",
Email = "[email protected]",
EmailConfirmed = true
};

await userManager.CreateAsync(adminUser, "Admin123!");
}

if (!await userManager.IsInRoleAsync(adminUser, "Admin"))
{
await userManager.AddToRoleAsync(adminUser, "Admin");
}

// add admin role to external google user [email protected]
var googleUser = await userManager.FindByNameAsync("[email protected]");
if (googleUser != null)
{
if (!await userManager.IsInRoleAsync(googleUser, "Admin"))
{
await userManager.AddToRoleAsync(googleUser, "Admin");
}
}
Code to seed users (this works)
JakenVeina
JakenVeina14mo ago
or go back to a blank template and start adding things incrementally until it stops working
Very Funny
Very FunnyOP14mo ago
if it helps this is a .NET 8 project oh oh oh I think I know what might be doing it in I don't think I broke it. I think it was broken to begin with My Server project has no _framework/blazor.web.js In hindsight, I think what I mentioned above is wrong
JakenVeina
JakenVeina14mo ago
which part?
Very Funny
Very FunnyOP14mo ago
about the _framework cause my .Client doesn't have it and the @onclick in there works fine
JakenVeina
JakenVeina14mo ago
it's definitely present in a fresh template where this works fine, BTW
<button class="btn btn-primary" @onclick="@(() => IncrementCountBy(2))">Click me</button>
<button class="btn btn-primary" @onclick="@(() => IncrementCountBy(2))">Click me</button>
Very Funny
Very FunnyOP14mo ago
FYI this is my setup for the project
No description
JakenVeina
JakenVeina14mo ago
so, yeah, I'm gonna re-iterate my recommendation again okay see that's what you should lead with
Very Funny
Very FunnyOP14mo ago
gonna be honest, though I had. mb
JakenVeina
JakenVeina14mo ago
you said ".NET 8.0" and "Blazor" and then we established later that this is "server" this is in fact not Blazor Server, it's the whole new deal
Very Funny
Very FunnyOP14mo ago
ahh didn't realise
JakenVeina
JakenVeina14mo ago
so, now we go back to my very first question rather, my very first response
that proves nothing set a breakpoint
setting a breakpoint in your server code proves nothing your server code IS NOT WHAT'S RUNNING not when you click the button
Very Funny
Very FunnyOP14mo ago
So do I have to move at least the button to inside .Client? Or is it still possible to achieve it the way I first intended?
JakenVeina
JakenVeina14mo ago
the whole point of "Interactive render mode" of "Auto (Server and WebAssembly)" is that pages are rendered server-side, on startup, but rendering transitions over to the client, as soon as the app bootstraps so, yes a button handler in server-side code is nonsense
Very Funny
Very FunnyOP14mo ago
so stick the button handler in the client side, then put the functionality in the server side?
JakenVeina
JakenVeina14mo ago
which functionality? the only functionality that should exist server-side is what needed for startup
Very Funny
Very FunnyOP14mo ago
Stuff like this
c#
@code
{
public List<UserInfo> Users { get; set; } = new ();

public void Greet()
{
Console.WriteLine("Greet");
}

protected override async Task OnInitializedAsync()
{
var users = await UserManager.Users.ToListAsync();
foreach (var user in users)
{
var roles = await UserManager.GetRolesAsync(user);
var userInfo = new UserInfo
{
UserId = user.Id,
UserName = user.UserName,
Email = user.Email,
Roles = new List<string>(roles),
IsAdmin = roles.Contains("Admin")
};
Users.Add(userInfo);
}
}

public async Task PromoteUser(string userId)
{
Console.WriteLine("PromoteUser");
var user = await UserManager.FindByIdAsync(userId);
await UserManager.AddToRoleAsync(user, "Admin");
await OnInitializedAsync();
}

public async Task DemoteUser(string userId)
{
Console.WriteLine("DemoteUser");
var user = await UserManager.FindByIdAsync(userId);
await UserManager.RemoveFromRoleAsync(user, "Admin");
await OnInitializedAsync();
}
}
c#
@code
{
public List<UserInfo> Users { get; set; } = new ();

public void Greet()
{
Console.WriteLine("Greet");
}

protected override async Task OnInitializedAsync()
{
var users = await UserManager.Users.ToListAsync();
foreach (var user in users)
{
var roles = await UserManager.GetRolesAsync(user);
var userInfo = new UserInfo
{
UserId = user.Id,
UserName = user.UserName,
Email = user.Email,
Roles = new List<string>(roles),
IsAdmin = roles.Contains("Admin")
};
Users.Add(userInfo);
}
}

public async Task PromoteUser(string userId)
{
Console.WriteLine("PromoteUser");
var user = await UserManager.FindByIdAsync(userId);
await UserManager.AddToRoleAsync(user, "Admin");
await OnInitializedAsync();
}

public async Task DemoteUser(string userId)
{
Console.WriteLine("DemoteUser");
var user = await UserManager.FindByIdAsync(userId);
await UserManager.RemoveFromRoleAsync(user, "Admin");
await OnInitializedAsync();
}
}
Or does all of that go into my client as well?
Very Funny
Very FunnyOP14mo ago
I suppose I could always set up services and controllers to manage endpoints that achieve the same thing. Have my client call the endpoints Sense has been made
JakenVeina
JakenVeina14mo ago
more likely, it seems like you have not defined this component as interactive
Very Funny
Very FunnyOP14mo ago
c#
builder.Services.AddRazorComponents()
.AddInteractiveServerComponents()
.AddInteractiveWebAssemblyComponents();

app.MapRazorComponents<App>()
.AddInteractiveServerRenderMode()
.AddInteractiveWebAssemblyRenderMode()
.AddAdditionalAssemblies(typeof(Counter).Assembly);
c#
builder.Services.AddRazorComponents()
.AddInteractiveServerComponents()
.AddInteractiveWebAssemblyComponents();

app.MapRazorComponents<App>()
.AddInteractiveServerRenderMode()
.AddInteractiveWebAssemblyRenderMode()
.AddAdditionalAssemblies(typeof(Counter).Assembly);
This is in my server side Program.cs
JakenVeina
JakenVeina14mo ago
Components using the automatic render mode must be built from a separate client project that sets up the Blazor WebAssembly host. You can't switch to a different interactive render mode in a child component. For example, a Server component can't be a child of a WebAssembly component.
Very Funny
Very FunnyOP14mo ago
does that mean I can't have the client call endpoints that are located in the server? cause thats what I am probably gonna try when I get back
JakenVeina
JakenVeina14mo ago
that is not what it means
Very Funny
Very FunnyOP14mo ago
ok good, just wanted to make sure

Did you find this page helpful?