I’m using the FluentUI Blazor components in an app, created using the Fluent UI Blazor Web App template, so I have both server and client projects. That’s all fine.
I’m adding a component to be displayed in the menu bar which shows “Login” if not already logged in, or an avatar using the FluentProfileMenu control if you are logged in.
My MainLayout.razor file is as follows (some items removed as not necessary for this issue)…
<FluentLayout>
<FluentHeader>
Title here
<FluentSpacer/>
<LoginView/>
</FluentHeader>
<snip/>
</FluentLayout>
LoginView is a .razor component that displays “Login” if you’re not logged in, or the FluentProfileMenu if you are logged in. I have re-templated the control such that there’s a Logout link in the title section…
<AuthorizeView>
<Authorized>
<FluentProfileMenu Image="@_image"
TopCorner="true"
FullName="@_name"
EMail="@_username"
HeaderLabel="@_title">
<HeaderTemplate>
<FluentStack VerticalAlignment="@VerticalAlignment.Center">
@if (!string.IsNullOrEmpty(_title))
{
<FluentLabel part="header-label">@_title</FluentLabel>
}
<FluentSpacer />
<form action="Account/Logout" method="post">
<AntiforgeryToken />
<input type="hidden" name="ReturnUrl" value="@currentUrl" />
<FluentButton Type="ButtonType.Submit"
Appearance="@Appearance.Stealth">Logout</FluentButton>
</form>
</FluentStack>
</HeaderTemplate>
</FluentProfileMenu>
</Authorized>
<NotAuthorized>
<FluentNavLink Href="Account/Login?redirectUri=/">Log in</FluentNavLink>
</NotAuthorized>
</AuthorizeView>
When I run this code I get what I expect, a nice profile menu when I’m logged in and a button with a title “Logout” that when clicked attempts to navigate to Account/Logout.
The problem happens when I click the Logout button – I get an error from the server…
AntiforgeryValidationException: The required antiforgery request token was not
provided in either form field "__RequestVerificationToken" or header value
"RequestVerificationToken".
Inspecting the form fields, I can indeed see that the __RequestVerificationToken does not exist. I have found a workaround, and that is to move my form definition around the outside of the FluentProfileMenu control as follows…
<AuthorizeView>
<Authorized>
<form action="Account/Logout" method="post"> <--- Form moved up above the menu
<AntiforgeryToken /> <--- And this little puppy put here too
<FluentProfileMenu Image="@_image"
TopCorner="true"
FullName="@_name"
EMail="@_username"
HeaderLabel="@_title">
<HeaderTemplate>
<FluentStack VerticalAlignment="@VerticalAlignment.Center">
@if (!string.IsNullOrEmpty(_title))
{
<FluentLabel part="header-label">@_title</FluentLabel>
}
<FluentSpacer />
<input type="hidden" name="ReturnUrl" value="@currentUrl" />
<FluentButton Type="ButtonType.Submit"
Appearance="@Appearance.Stealth">Logout</FluentButton>
</FluentStack>
</HeaderTemplate>
</FluentProfileMenu>
</form>
</Authorized>
<NotAuthorized>
<FluentNavLink Href="Account/Login?redirectUri=/">Log in</FluentNavLink>
</NotAuthorized>
</AuthorizeView>
I can live with this workaround – but why is it needed? Why is the __RequestVerificationToken value not being rendered into the HTML in the original example? I’m clearly missing something here, and I’m a noob when it comes to Blazor, but this doesn’t make sense to me.
In my form definition all I have is this…
<form action="Account/Logout" method="post">
<AntiforgeryToken />
<input type="hidden" name="ReturnUrl" value="@currentUrl" />
<FluentButton Type="ButtonType.Submit"
Appearance="@Appearance.Stealth">Logout</FluentButton>
</form>
Everything but the __RequestVerificationToken value is being rendered into the HTML. Looking at this in DevTools, I see the form, hidden input value, button etc. – but the __RequestVerificationToken is missing in action…
<form action="Account/Logout" method="post">
<!--!-->
<!--!-->
<input type="hidden" name="ReturnUrl" value="">
<!--!-->
<!--!-->
<!--!-->
<fluent-button type="submit" appearance="stealth" class="stealth" b-x1200685t0="" _bl_4="" current-value="">Logout</fluent-button>
</form>
Something is removing the token, or not rendering it in the first place when I use my original code, but I can’t work out what I’m doing wrong.
Any guidance would be gratefully received, thanks in advance for your comments.