有可能有按钮"外部注册";放在里面。剃须刀页(服务器端(?
下面的代码来自ExternalRegister.cs.html,但我希望将这两个注册按钮(谷歌、脸书(作为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>
是的,在剃刀页面中可以有这些按钮。
当然,要做到这一点,您需要能够枚举可用的提供者,这意味着您需要将它们从传递到Blazor应用程序_Host.cshtml(或任何您托管Blazor应用程序的地方(
注意:不能传递AuthenticationScheme
的列表,因为.NET不会串行化它们,这就是为什么我将它们转换为DTOExternalProvider
@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 PageModel(Code Behind(中定义两个OnPost方法。例如:
public void OnPostFaceBook(ExternalLogin provider)
{
//your code here
}
public void OnPostGoogle(ExternalLogin provider)
{
//your code here
}
在.cs.html文件中,为每个表单放置两个单独的表单,并添加参数asp页面处理程序到每个提交按钮。例如:
<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>