1

I am trying to execute an asynchronous method when pressing a button. The code compiles without issue, but when the button is clicked the method is never called. I have used all the google fu i have at my disposal to no avail. Am I doing something wrong syntactically? Did i forget to import something or am i misunderstanding how this works?

  @foreach (Data.Course cor in CourseList)
                    { 
/...
<button class="btn btn-outline-primary" @onclick="@(async () => await EnrollCourse(cor.CourseId))">
                                        Enroll
                                    </button>
}

@functions{
    private async Task EnrollCourse(int corid)
    {
        var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync();
        string userid = authState.User.Identity.Name;
        await _db.EnrollCourse(corid, userid);
        NavigationManager.NavigateTo($"/course/{corid}");
        
    }



}

5
  • string userid = authState.User.Identity.Name; Isnt this an email not not the Id? Commented Jul 30, 2020 at 21:42
  • How do you know the method has never been called ? Commented Jul 30, 2020 at 22:16
  • Yeah i verified it with the debugger that the method is never being executed, also the data does not get populated into the db Commented Jul 31, 2020 at 1:04
  • Does @functions still work? What Blazor version are you using? Commented Jul 31, 2020 at 5:18
  • @HenkHoltermanI Ive tried in the code block and the function block, from what ive seen most people seem to put code like this in the function block. Whatever the latest version is Commented Aug 1, 2020 at 0:48

2 Answers 2

1

For anyone that comes around to this on google, i ended up setting the button to redirect to a different page that runs the code and redirects to the final page.

<div class="button">
    <a href="/enroll/@cor.CourseId">Enroll</a>
</div>
@page "/enroll/{course}"
@inject Data.CourseData _db
@inject NavigationManager NavigationManager
@inject AuthenticationStateProvider AuthenticationStateProvider
@inject Microsoft.AspNetCore.Identity.UserManager<Microsoft.AspNetCore.Identity.IdentityUser> userManager
@using System.Security.Claims


@code {
    [Parameter]
    public string course { get; set; }
    protected override async Task OnInitializedAsync()
    {
        var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync();

        var user = await userManager.GetUserAsync(authState.User);
        if (user != null)
        {
            string userid = user.Id;
            await _db.EnrollCourse(Int32.Parse(course), userid);
            NavigationManager.NavigateTo("/course/" + Int32.Parse(course));


        }
    }

}
Sign up to request clarification or add additional context in comments.

Comments

0

Please note how I am collecting the User Id. I hope this helps. Your user manager may be of type UserManager<ApplicationUser> as well...

    @inject UserManager<ApplicationUser> userManager
    @using System.Security.Claims
    .....
    <AuthorizeView>
          @foreach (Data.Course cor in CourseList)
                    { 
/...
<button class="btn btn-outline-primary" @onclick="@(async () => await EnrollCourse(cor.CourseId,context.User))">
                                        Enroll
                                    </button>
}
    </AuthorizeView>
@functions{
     private async Task EnrollCourse(int corid, ClaimsPrincipal identity)
     {

        var user = await userManager.GetUserAsync(identity);

        var userid = user.Id;
        await _db.EnrollCourse(corid, userid);
        NavigationManager.NavigateTo($"/course/{corid}");
        
     }



}

6 Comments

Yeah, I dug through the docs and could not find a way to get the actual userid so i just had to settle on using the username instead. Im not sure what user id your implementation is referencing as in my database the user id is a string not an int. Im using the default authenticationstateprovider library via @inject AuthenticationStateProvider AuthenticationStateProvider
@MaxTE7 switch it to UserManager<ApplicationUser> that is a string key. Individual accounts on blazer server-side must be ints. Injecting the AuthenticationStateProvider should work as well. If the user cant use the function why show the button. That is why I used <AuthorizeView> . It provided the context so there was no need to call GetAuthenticationStateAsync().
I am actually creating the buttons inside an authorized view, so i can use your method of getting the context, but, when I try to inject Microsoft.AspNetCore.Identity.UserManager<ApplicationUser> i get a namespace not found error. I am using the default user based authentication built into blazor if that helps
i figured it out. var user = userManager.GetUserAsync(identity); should be var user = await userManager.GetUserAsync(identity);. Then the user is retrieved properly
FYI: var userId = identity.FindFirst(c => c.Type == "sub")?.Value; works on client-side
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.