我使用Blazor WASM和AzureB2C来调用Azure函数中托管的API。我想在成功登录时调用我的API,将用户信息添加/更新到数据库中。我一直在遵循这个指南。当试图将我键入的httpclient注入AccountClaimsPrincipalFactory时,我遇到了一个运行时错误:
Microsoft.AspNetCore.Components.WebAssembly.Frendering.WebAssemblyRenderer[100]呈现组件时出现未处理的异常:ValueFactory试图访问此实例的Value属性。System.InvalidOperationException:ValueFactory试图访问此实例的Value属性。
这在浏览器中显示,但应用程序编译和运行都很好。如果我不注入PlatformServiceClient
,代码会很好地工作,但我需要调用API来记录用户。涉及以下文件。我调整了一些事情以简化。这似乎是一种合适的方法,但我还没有看到在索赔工厂中进行api调用的例子。
CustomAccountFactory.cs
public class CustomAccountFactory: AccountClaimsPrincipalFactory<CustomUserAccount>
{
public IPlatformServiceClient client { get; set; }
public CustomAccountFactory(NavigationManager navigationManager,
IPlatformServiceClient platformServiceClient,
IAccessTokenProviderAccessor accessor) : base(accessor)
{
client = platformServiceClient;
}
public override async ValueTask<ClaimsPrincipal> CreateUserAsync(
CustomUserAccount account, RemoteAuthenticationUserOptions options)
{
var initialUser = await base.CreateUserAsync(account, options);
if (initialUser.Identity.IsAuthenticated)
{
//call the API here
await client.RegisterUserAsync();
}
return initialUser;
}
}
Program.cs
摘录
builder.Services.AddScoped<CustomAuthorizationMessageHandler>();
builder.Services.AddHttpClient<IPlatformServiceClient, PlatformServiceClient>(
client => client.BaseAddress = new Uri(builder.Configuration["PlatformServiceUrl"]))
.AddHttpMessageHandler<CustomAuthorizationMessageHandler>();
builder.Services.AddMsalAuthentication<RemoteAuthenticationState, CustomUserAccount>(options =>
{
builder.Configuration.Bind("AzureAd", options.ProviderOptions.Authentication);
options.ProviderOptions.DefaultAccessTokenScopes.Add("openid");
options.ProviderOptions.DefaultAccessTokenScopes.Add("offline_access");
options.ProviderOptions.DefaultAccessTokenScopes.Add("access_as_user");
options.ProviderOptions.LoginMode = "redirect";
options.UserOptions.RoleClaim = "roles";
}).AddAccountClaimsPrincipalFactory<RemoteAuthenticationState, CustomUserAccount, CustomAccountFactory>();
CustomAuthorizationMessageHandler.cs
public class CustomAuthorizationMessageHandler : AuthorizationMessageHandler
{
public CustomAuthorizationMessageHandler(IAccessTokenProvider provider,
NavigationManager navigationManager)
: base(provider, navigationManager)
{
ConfigureHandler(
authorizedUrls: new[] { "http://localhost:7071" },
scopes: new[] { "access_as_user" });
}
}
我通过创建客户端的命名实例并将IHttpClientFactory传递到CustomAccountFactory来解决此问题。
builder.Services.AddHttpClient<PlatformServiceClient>("PlatformServiceClient",
client => client.BaseAddress = new Uri(builder.Configuration["PlatformServiceUrl"]))
.AddHttpMessageHandler<CustomAuthorizationMessageHandler>();
在那里我可以创建一个客户端,但我必须手动设置我的url,而不是使用我已经完成这项工作的类型化客户端。
var client = factory.CreateClient("PlatformServiceClient");
var response = await client.GetAsync("/user/me");
在调用AddMsalAuthenification 之前,我还注册了新客户端
builder.Services.AddTransient(sp => sp.GetRequiredService<IHttpClientFactory>().CreateClient("PlatformServiceClient"));
我按照编码火烈鸟在这里找到的代码做了所有这些。一切都按预期进行。