Blazor 服务器端,.razor 页面上的 ExternalRegister 按钮
Blazor Server side, ExternalRegister buttons at .razor page
是否可以将“外部注册”按钮放置在 .razor 页面(服务器端)内?
以下代码来自 ExternalRegister.cshtml,但我希望将这两个注册按钮(Google、Facebook)作为 Start.razor 页面的一部分。这可能吗?
@model Aplication.Areas.Identity.Pages.Account.ExternalRegisterModel
<form id="external-account" asp-page="./ExternalLogin" asp-route-returnUrl="@Model.ReturnUrl" method="post" class="form-horizontal">
<div>
<p>
@foreach (var provider in Model.ExternalLogins)
{
<button type="submit" class="btn btn-primary" name="provider" value="@provider.Name" title="Log in using your @provider.DisplayName account">@provider.DisplayName</button>
}
</p>
</div>
</form>
我认为最好的策略是在你的 Razor PageModel 中定义两个 OnPost 方法 (Code-Behind)。例如:
public void OnPostFaceBook(ExternalLogin provider)
{
//your code here
}
public void OnPostGoogle(ExternalLogin provider)
{
//your code here
}
然后在您的 .cshtml 文件中为每个放置两个单独的表单,并添加参数
asp-page-handler
到每个提交按钮。例如:
<button type="submit" class="btn btn-primary" value="FaceBook" value="FaceBook" asp-page-handler="FaceBook">Log in using your FaceBook account</button>
以及其他形式:
<button type="submit" class="btn btn-primary" value="Google" value="Google" asp-page-handler="Google">Log in using your Google account</button>
是的,可以在剃须刀页面中添加按钮。
当然,为此,您需要能够枚举可用的提供程序,这意味着您需要将它们从
_Host.cshtml(或托管 Blazor 应用程序的任何位置)
注意:您不能传递 AuthenticationScheme
的列表,因为 .NET 不会将它们序列化,这就是我将它们转换为 DTO ExternalProvider
的原因
@inject Microsoft.AspNetCore.Antiforgery.IAntiforgery Xsrf
@inject SignInManager<IdentityUser> _signInManager
@{
var state = new InitialApplicationState
{
XsrfToken = Xsrf.GetAndStoreTokens(HttpContext).RequestToken,
ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync())
.ToList()
.Select(scheme=>
new ExternalProvider {Name=scheme.Name, DisplayName=scheme.DisplayName}
)
};
}
<component type="typeof(App)" param-InitialState="state" render-mode="ServerPrerendered" />
InitialApplicationState
和 ExternalProvider
是简单的 DTO 类
public class InitialApplicationState
{
public string XsrfToken { get; set; }
public IEnumerable<ExternalProvider> ExternalLogins { get; set; }
}
public class ExternalProvider
{
public string Name { get; set; }
public string DisplayName { get; set; }
}
现在,您需要在 Blazor 代码中将此数据作为 App.razor
组件上的 Parameter
@inject InitialApplicationState InitialStateService
@code {
[Parameter] public InitialApplicationState InitialState { get; set; } = default;
protected override Task OnInitializedAsync()
{
InitialStateService.XsrfToken = InitialState.XsrfToken;
InitialStateService.ExternalLogins = InitialState.ExternalLogins;
return base.OnInitializedAsync();
}
}
我们在这里所做的就是声明将接收我们的 InitialApplicationState
的 Parameter
InitialState
- 然后我们将该状态存储在已配置的服务 InitialStateService
中在 startup.cs
作为 Scoped 依赖项。
builder.Services.AddScoped<InitialApplicationState>();
现在,我们在 Blazor 的 DI 容器中有一项服务,其中包含可用的外部身份验证提供程序列表和我们的伪造保护令牌。
我们可以在 Blazor 中需要的任何地方注入 InitialApplicationState
,例如Index.razor
并枚举 ExternalLogins
以呈现按钮
Blazor 中的表单声明略有不同,因为我们没有 asp*
指令:
@inject InitialApplicationState InitialStateService
<form id="external-account"
action="/Identity/Account/ExternalLogin"
method="post">
<div>
<p>
@foreach (var provider in InitialStateService.ExternalLogins)
{
<button type="submit"
name="provider"
value="@provider.Name"
title="Log in using your @provider.DisplayName account">
@provider.DisplayName
</button>
}
</p>
</div>
<input name="__RequestVerificationToken" type="hidden"
value="@InitialStateService.XsrfToken">
</form>
是否可以将“外部注册”按钮放置在 .razor 页面(服务器端)内?
以下代码来自 ExternalRegister.cshtml,但我希望将这两个注册按钮(Google、Facebook)作为 Start.razor 页面的一部分。这可能吗?
@model Aplication.Areas.Identity.Pages.Account.ExternalRegisterModel
<form id="external-account" asp-page="./ExternalLogin" asp-route-returnUrl="@Model.ReturnUrl" method="post" class="form-horizontal">
<div>
<p>
@foreach (var provider in Model.ExternalLogins)
{
<button type="submit" class="btn btn-primary" name="provider" value="@provider.Name" title="Log in using your @provider.DisplayName account">@provider.DisplayName</button>
}
</p>
</div>
</form>
我认为最好的策略是在你的 Razor PageModel 中定义两个 OnPost 方法 (Code-Behind)。例如:
public void OnPostFaceBook(ExternalLogin provider)
{
//your code here
}
public void OnPostGoogle(ExternalLogin provider)
{
//your code here
}
然后在您的 .cshtml 文件中为每个放置两个单独的表单,并添加参数 asp-page-handler 到每个提交按钮。例如:
<button type="submit" class="btn btn-primary" value="FaceBook" value="FaceBook" asp-page-handler="FaceBook">Log in using your FaceBook account</button>
以及其他形式:
<button type="submit" class="btn btn-primary" value="Google" value="Google" asp-page-handler="Google">Log in using your Google account</button>
是的,可以在剃须刀页面中添加按钮。
当然,为此,您需要能够枚举可用的提供程序,这意味着您需要将它们从 _Host.cshtml(或托管 Blazor 应用程序的任何位置)
注意:您不能传递 AuthenticationScheme
的列表,因为 .NET 不会将它们序列化,这就是我将它们转换为 DTO ExternalProvider
的原因
@inject Microsoft.AspNetCore.Antiforgery.IAntiforgery Xsrf
@inject SignInManager<IdentityUser> _signInManager
@{
var state = new InitialApplicationState
{
XsrfToken = Xsrf.GetAndStoreTokens(HttpContext).RequestToken,
ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync())
.ToList()
.Select(scheme=>
new ExternalProvider {Name=scheme.Name, DisplayName=scheme.DisplayName}
)
};
}
<component type="typeof(App)" param-InitialState="state" render-mode="ServerPrerendered" />
InitialApplicationState
和 ExternalProvider
是简单的 DTO 类
public class InitialApplicationState
{
public string XsrfToken { get; set; }
public IEnumerable<ExternalProvider> ExternalLogins { get; set; }
}
public class ExternalProvider
{
public string Name { get; set; }
public string DisplayName { get; set; }
}
现在,您需要在 Blazor 代码中将此数据作为 App.razor
组件上的 Parameter
@inject InitialApplicationState InitialStateService
@code {
[Parameter] public InitialApplicationState InitialState { get; set; } = default;
protected override Task OnInitializedAsync()
{
InitialStateService.XsrfToken = InitialState.XsrfToken;
InitialStateService.ExternalLogins = InitialState.ExternalLogins;
return base.OnInitializedAsync();
}
}
我们在这里所做的就是声明将接收我们的 InitialApplicationState
的 Parameter
InitialState
- 然后我们将该状态存储在已配置的服务 InitialStateService
中在 startup.cs
作为 Scoped 依赖项。
builder.Services.AddScoped<InitialApplicationState>();
现在,我们在 Blazor 的 DI 容器中有一项服务,其中包含可用的外部身份验证提供程序列表和我们的伪造保护令牌。
我们可以在 Blazor 中需要的任何地方注入 InitialApplicationState
,例如Index.razor
并枚举 ExternalLogins
以呈现按钮
Blazor 中的表单声明略有不同,因为我们没有 asp*
指令:
@inject InitialApplicationState InitialStateService
<form id="external-account"
action="/Identity/Account/ExternalLogin"
method="post">
<div>
<p>
@foreach (var provider in InitialStateService.ExternalLogins)
{
<button type="submit"
name="provider"
value="@provider.Name"
title="Log in using your @provider.DisplayName account">
@provider.DisplayName
</button>
}
</p>
</div>
<input name="__RequestVerificationToken" type="hidden"
value="@InitialStateService.XsrfToken">
</form>