wasm 访问html元素,blazor wasm访问非本地的restful service

准备工作

blazor wasm正式版发布了!在尝试使用的过程中,发现几个小坑,跟大家分享一下,希望有所帮助。

我是通过keycloak来保护blazor和service的,如何保护service请参考我之前的随笔,此处不再重复说明。

启动一个新的wasm项目,包含身份认证,但不是hosted(web前端和service在同一个网址),也就是最常见的web和service分别开发和分别部署的场景,使用如下命令新建项目:

dotnet new blazorwasm -o {存放路径} --au Individual

自动生成客户端代码

由于我的service采用了openapi,因此在wasm项目中,可以借助openapi代码生成工具,自动生成客户端代码,节约开发时间。这个步骤不是必须的,但是个人建议这样做。

首先,如果没有安装工具,先安装工具:

dotnet tool install -g microsoft.dotnet-openapi

然后,运行命令生成客户端代码:

dotnet openapi add url http://localhost:5000/swagger/v1/swagger.json --output-file Weather.json

以上工具只是将json文件注册到项目中,项目中还必须安装NSWag.CodeGeneration.CSharp,才能正常生成客户端代码,为了方便大家参考,将所有需要引用的包都写在这儿了。

netstandard2.1

3.0

为了保证代码能够顺利生成,可以运行dotnet build命令,如果成功,Obj目录会出现一个WeatherClient.cs文件,其中包含了model和service。因为他使用了Newtonsoft.Json,所以要添加这个包的引用。

配置oidc

模板包含了oidc的基本配置,修改配置文件中的地址和客户端名称即可连接到openid服务。

实际操作中遇到几个坑:

无法获得access token或者json解析错误

无法获得用户名

访问service时,无法自动添加acess token到请求头部

无法获得access token

主要是app默认采用implicit认证流程,keycloak默认没有开启该流程,而且开启后,会无法解析json。

解决方法,修改program.cs,在builder.Services.AddOidcAuthentication中添加如下代码

options.ProviderOptions.ResponseType = "code";

修改认证流程为标准流程。

无法获得用户名

keycloak使用preferred_username发送用户名信息,而.net默认需要name字段,两边不匹配。

解决方法,要么修改这边,要么修改那边。

方法1:修改keycloak的client scopes – profile – mappers – username,修改”Token Claim Name”的内容为”name”

方法2:在builder.Services.AddOidcAuthentication中添加如下代码

options.UserOptions.NameClaim = "preferred_username";

访问service时,无法自动添加acess token到请求头部

这是最大的一个坑。

官方模板和文档中,总是在说如何访问自己hosted的service,但是实际使用中,app和service往往在不同的服务器上,官方文档最这种情况作了说明,但是如果不很细致的看文档,就容易理解错。

最主要的一点就是:BaseAddressAuthorizationMessageHandler只能给本地地址的请求加token,并不能处理不同服务器的情况。

下面是我的解决方法:

1 var clientName = "BlazorWithIdentity.ServerAPI";2 var baseUrl = builder.Configuration.GetValue("ApiBaseUrl");3

4 builder.Services.AddHttpClient(clientName, client => client.BaseAddress = newUri(baseUrl))5 .AddHttpMessageHandler(sp => sp.GetRequiredService()6 .ConfigureHandler(new[] { baseUrl }));7

8 builder.Services.AddTransient(sp => sp.GetRequiredService()9 .CreateClient(clientName));10

11 builder.Services.AddTransient(s =>

12 new WeatherClient(null, s.GetRequiredService().CreateClient(clientName)));

4行:注入名称为clientName的客户端,并且设置handler,对于来自baseUrl的所有请求自动添加Auth头;

8行:注入HttpClient,在页面上通过 @inject HttpClient Http,就可以使用自带Auth头部的HttpClient了;

11行:注入自动生成的WeatherClient,使用4行的HttpClient

页面调用service访问数据

经过前面的各种配置,页面访问数据就很简单了,如下:

@page "/fetchdata"@using Microsoft.AspNetCore.Authorization

@inject WeatherClient Client

@attribute [Authorize]

Weather forecast

This component demonstrates fetching data from the server.

@if (forecasts== null)

{

Loading...

}else{

DateTemp. (C)Temp. (F)Summary

@foreach (var forecast inforecasts)

{

@forecast.Date.Date.ToShortDateString()@forecast.TemperatureC@forecast.TemperatureF@forecast.Summary}}

@code {private IEnumerableforecasts;protected override asyncTask OnInitializedAsync()

{

forecasts= awaitClient.WeatherForecastAsync();

}

}

怎么样,是不是很简洁的代码?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值