前端 JS/TS 调用 ASP.NET Core gRPC-Web

前言

在上两篇文章中,介绍了ASP.NET Core 中的 gRPC-Web 实现 和 在 Blazor WebAssembly 中使用 gRPC-Web,实现了 Blazor WebAssembly 调用 ASP.NET Core gRPC-Web。虽然 ASP.NET Core 中的 gRPC-Web 实现目前还是试验性项目,但是鉴于它在生态上的重大意义,说不定我们很快就能在正式版本中使用。

虽然 Blazor WebAssembly 现在已经是 .NET 进军前端的大热门,但有同学说,只介绍了 Blazor WebAssembly 的调用方法还不够呀,现在比较常用的还是 JS/TS 前端,那么本篇,我就介绍一下在前端 JS/TS 中调用 ASP.NET Core gRPC-Web。

其实 gRPC-Web 项目本身,就是为 JS/TS 提供 gRPC 能力的,让不支持 HTTP/2 的客户端和服务端也能使用 gRPC 的大部分特性。gRPC-Web 项目提供了一个 protoc CLI 插件,可用于把 proto 协议文件转换为 JS/TS 语言可导入的对应 gRPC 服务的客户端,还生成了 .d.ts 文件来支持 Typescript。

示例

接下来,我就来展示一下,用 Visual Studio 自带的 ASP.NET Core + Angular 模板创建的项目,把原来的 WebApi 调用改造成 gRPC-Web 调用。

本示例基于 .NET Core 3.1,请安装好最新的 .NET Core SDK 和 Visual Studio 2019。

创建项目

打开 Visual Studio 2019,创建新项目 -> 选择"ASP.NET Core Web 应用程序" -> 填写项目名 -> 选择 "Angular" 项目模板。如图:

我们就是用这个项目,把 fetch-data 页面获取数据的方式修改为 gRPC-Web 。

添加 gRPC proto 文件

在项目中新建一个目录 Protos,创建文件 weather.proto :

syntax = "proto3";import "google/protobuf/empty.proto";
import "google/protobuf/timestamp.proto";option csharp_namespace = "AspNetCoreGrpcWeb";package WeatherForecast;service WeatherForecasts {rpc GetWeather (google.protobuf.Empty) returns (WeatherReply);
}message WeatherReply {repeated WeatherForecast forecasts = 1;
}message WeatherForecast {google.protobuf.Timestamp dateTimeStamp = 1;int32 temperatureC = 2;int32 TemperatureF = 3;string summary = 4;
}

可以看到 proto 中导入了官方库的其他 proto 文件,它们是编译用的辅助文件。对于.NET Core 项目,可以通过引用 Google.Protobuf 这个包引入。

修改 ASP.NET Core 服务端

我们先修改服务端,让 ASP.NET Core 提供 gRPC-Web 服务。

由于 gRPC-Web 包还没有发布到 NuGet.org,现在你需要添加一个临时的包管理源来获得 nightly 预览。在你的解决方案的根目录下添加NuGet.config文件:

<?xml version="1.0" encoding="utf-8"?>
<configuration><packageSources><!--To inherit the global NuGet package sources remove the <clear/> line below --><clear /><add key="nuget" value="https://api.nuget.org/v3/index.json" /><add key="gRPC-nightly" value="https://grpc.jfrog.io/grpc/api/nuget/v3/grpc-nuget-dev" /></packageSources>
</configuration>

再添加必要的 Nuget 包引用:

<PackageReference Include="Grpc.AspNetCore" Version="2.27.0-dev202001100801" />
<PackageReference Include="Grpc.AspNetCore.Web" Version="2.27.0-dev202001100801" />

接着,修改原来的 WeatherForecastController 改为 WeatherForecastService:

    public class WeatherForecastsService : WeatherForecasts.WeatherForecastsBase{private static readonly string[] Summaries = {"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"};public override Task<WeatherReply> GetWeather(Empty request, ServerCallContext context){var reply = new WeatherReply();var rng = new Random();reply.Forecasts.Add(Enumerable.Range(1, 5).Select(index =>{var temperatureC = rng.Next(-20, 55);return new WeatherForecast{DateTimeStamp = Timestamp.FromDateTime(DateTime.UtcNow.AddDays(index)),TemperatureC = temperatureC,TemperatureF = 32 + (int)(temperatureC / 0.5556),Summary = Summaries[rng.Next(Summaries.Length)]};}));return Task.FromResult(reply);}}

现在,在你的服务器的 Startup.cs 文件中,修改 ConfigureServices 以添加以下行:

  services.AddGrpc();

注意:如果你只打算公开 gRPC 服务,你可能不再需要 MVC 控制器,在这种情况下,你可以从下面删除services.AddMvc()endpoints.MapDefaultControllerRoute()

只是在 app.AddRouting(); 的下面添加以下内容,它会处理将传入的 gRPC-web 请求映射到服务端,使其看起来像 gRPC 请求:

  app.UseGrpcWeb();

最后,在app.UseEndpoints语句块中注册你的 gRPC-Web 服务类,并在该语句块的顶部使用以下代码行:

  endpoints.MapGrpcService<WeatherForecastsService>().EnableGrpcWeb();

就这样,你的 gRPC-Web 服务端已经准备好了!

修改 Angular 项目

项目的 ClientApp 目录中,就是 Angular 的项目文件,使用 ASP.NET Core 托管,是这个项目模板约定的。

我们需要先通过 proto 生成需要的 js 文件。

安装 npm 包

运行命令:

 npm i protoc google-protobuf ts-protoc-gen @improbable-eng/grpc-web -s

生成 js 文件

在 ClientApp 目录下创建目录 proto ,再运行命令:

./node_modules/protoc/protoc/bin/protoc --plugin="protoc-gen-ts=.\node_modules\.bin\protoc-gen-ts.cmd" --js_out="import_style=commonjs,binary:./../Protos" --ts_out="service=grpc-web:src/app/proto" -I ./../Protos ../Protos/*.proto

可以在proto目录中看到生成了 4 个文件(每个 proto 会生成 4 个)

  • weather_pb_service.js: 包含了 rpc 调用客户端 WeatherForecastsClient

  • weather_pb.js: 包含了传输对象 WeatherForecast。这个文件在原 proto 的目录下,需要手动移过来。

  • 两个 *.d.ts 文件是对应以上两个文件的类型描述,用于 TS。

修改 fetch-data 页面组件

接下来,需要引用生成的文件,创建一个 WeatherForecastsClient 来调用 gRPC-Web 服务端。

  • fetch-data.component.ts

    import { Component } from '@angular/core';
    import { WeatherForecast } from '../proto/weather_pb';
    import { WeatherForecastsClient } from '../proto/weather_pb_service';
    import { Empty } from 'google-protobuf/google/protobuf/empty_pb';@Component({selector: 'app-fetch-data',templateUrl: './fetch-data.component.html',
    })
    export class FetchDataComponent {public forecasts: WeatherForecast[];private client: WeatherForecastsClient;constructor() {this.client = new WeatherForecastsClient('https://localhost:5001');this.client.getWeather(new Empty(), (error, reply) => {if (error) {console.error(error);}this.forecasts = reply.getForecastsList();});}
    }
    
  • fetch-data.component.html

    <h1 id="tableLabel">Weather forecast</h1><p>This component demonstrates fetching data from the server.</p><p *ngIf="!forecasts"><em>Loading...</em></p><table class="table table-striped" aria-labelledby="tableLabel" *ngIf="forecasts"><thead><tr><th>Date</th><th>Temp. (C)</th><th>Temp. (F)</th><th>Summary</th></tr></thead><tbody><tr *ngFor="let forecast of forecasts"><td>{{ forecast.getDatetimestamp().toDate() }}</td><td>{{ forecast.getTemperaturec() }}</td><td>{{ forecast.getTemperaturef() }}</td><td>{{ forecast.getSummary() }}</td></tr></tbody>
    </table>
    

可以看到:

  • 创建 WeatherForecastsClient 对象需要传入服务端的 HostName,要注意不要用 /后缀。

  • 生成出来的 WeatherForecast 类型包含getter/setter, 而 WeatherForecast.AsObject 类才是值对象,可以直接访问属性值,需要调用 .toObject() 方法进行转换。

  • datetimestamp 属性的类型 proto.google.protobuf.Timestamp 是 protobuf 里的关键字,调用 toDate() 方法可转换为 TS 的 Date 类型。

运行项目

完事具备,我们可以运行项目了。访问 https://localhost:5001/fetch-data,就可以看到前端是通过 gRPC-Web 获取数据了。

总结

可以看出,要在前端 JS/TS 使用 gRPC-Web 虽然在开发工具上没有 Blazor WebAssembly 方便,但是从 proto 生成客户端之后,前端的 TS 代码就能直接获得强类型的调用方法和路由,很简单地得到 gRPC 带来的好处。另外,gRPC-Web 项目本身已经 GA,所以我们可以先在后端使用它的 gRPC 代理,而前端可以放心大胆地在我们的生产项目中使用它。等到 ASP.NET Core 正式支持 gRPC-Web 后,就可以不需要代理了,比其他平台和语言都更有优势。

本示例的源码已发布到 Github:https://github.com/ElderJames/AspNetCoreGrpcWeb

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/311910.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据结构---哈夫曼树

数据结构—哈夫曼树 原理&#xff1a;参考趣学数据结构 代码&#xff1a; #include<stdio.h> #include<stdlib.h> #define N 100 #define INF 2^31-1 typedef struct fNode {//哈夫曼树中每个节点的信息int c;//字符int parent;//父节点&#xff0c;左右孩子&am…

热电偶校验仪_热电偶校验方法_烟台一等热电偶,干湿两用温度校验炉公司

杭州中创为您详细解读hzzc6烟台一等热电偶的相关知识与详情&#xff0c;防爆涡轮流量计的转速通过拆正在机壳外的传感线圈来检测&#xff0e;当涡轮流量计叶片切割由壳体内**磁钢发生的磁力线时&#xff0c;就会引起传感线圈中的磁通变革&#xff0e;传感线圈将检测到的磁通周期…

手把手教你用C#做疫情传播仿真

手把手教你用C#做疫情传播仿真在上篇文章中&#xff0c;我介绍了用 C#做的疫情传播仿真程序的使用和配置&#xff0c;演示了其运行效果&#xff0c;但没有着重讲其中的代码。今天我将抽丝剥茧&#xff0c;手把手分析程序的架构&#xff0c;以及妙趣横生的细节。首先来回顾一下运…

word List 10

word List 10 如果存在什么问题&#xff0c;欢迎批评指正&#xff01;谢谢&#xff01;

java程序员选择多个offer时需要看重哪些?_对不起,我们公司不要本科以下的大学生,学历对于程序员重不重要...

来自普通大学的学生&#xff0c;总会觉得逆袭如梦似幻&#xff0c;机会在哪里&#xff1f;但放长远来看&#xff0c;更重要的是要看到&#xff1a;环境只能影响&#xff0c;却不能决定我们的人生。人生路漫长&#xff0c;最终会怎样&#xff0c;还不一定呢&#xff01;在某综艺…

中小企业团队敏捷产品开发流程最佳实践

近期因为疫情的影响&#xff0c;不少互联网公司开始尝试远程工作。也出不了少如何做好远程工作的方法&#xff0c;我认为不管是场地办公还是远程办公都依赖于原来的产品开发流程。我曾经遵循CMMI5的流程管理过15人左右的跨国/语言/文化团队&#xff0c;也遵循敏捷Scrum管理过9人…

数据结构---二叉线索树

数据结构—二叉线索树 原理&#xff1a;参考趣学数据结构 代码&#xff1a; #include<stdio.h> #include<stdlib.h> typedef struct bmTree {int data;struct bmTree* lchild, *rchild;int ltag, rtag; }bmTree; bmTree * preNULL;//中序遍历的前驱指针 void cr…

revit如何根据坐标进行画线_铭成教你如何根据同步带的齿形进行选型

1、同步带齿形分类梯型齿同步带分为&#xff1a;最轻型MXL、超轻型XXL、特轻型XL、轻型L、重型H、特重型XH、超重型XXH&#xff0c;共七种&#xff0c;这几种是目前市场用的最广泛的。特殊齿型的同步带又分为&#xff1a;最轻型T2.5、轻型T5、重型T10、最重型T20&#xff0c;现…

在VS Code里逛知乎、发文章?知乎 on VS Code来啦!重新定义内容创作!

本文为 牛岱 的原创文章在2020年2月10日首发于“玩转VS Code”知乎专栏你是否已经厌倦了知乎 Web 端文本编辑器糟糕的使用体验和时而出现的奇怪 Bug&#xff1f;身为程序员的你是否想用你最熟悉的 Markdown 语法写答案&#xff0c;并且获得最佳的代码块语法高亮&#xff1f;攥写…

线性代数---向量问题的求解方法

线性代数—向量问题的求解方法 如果存在什么问题&#xff0c;欢迎批评指正&#xff01;谢谢&#xff01;

java 定时_Java线上定时任务不定期挂掉问题分析

作者&#xff1a;IKNOW本尊问题背景收到频繁的告警邮件&#xff0c;定时任务调度失败&#xff0c;查看xxl-job的执行器列表是空的&#xff0c;但是服务又显示健康&#xff0c;查看历史任务执行记录发现执行器是依次递减&#xff0c;由于是线上服务&#xff0c;只能先重启&#…

gRPC in ASP.NET Core 3.x -- Protocol Buffer, Go语言的例子(上)

前两篇文章半年前写的&#xff1a;gRPC in ASP.NET Core 3.0 -- Protocol Buffer&#xff08;1&#xff09;&#xff0c;gRPC in ASP.NET Core 3.0 -- Protocol Buffer&#xff08;2&#xff09;之前把protocol buffer的基础知识讲了一遍&#xff0c;今天使用Go语言做一些例子。…

word List 11

word List 11 如果存在什么问题&#xff0c;欢迎批评指正&#xff01;谢谢&#xff01;

温故知新 .Net重定向深度分析

在早期的.NET Framework程序员心里&#xff0c;重定向Redirect其实分为两种&#xff1a;Response.Redirect&#xff1a;Response对象的Redirect方法提供了一种实现客户端重定向的方法Server.Transfer&#xff1a;Server对象的Transfer方法使用服务器执行重定向&#xff0c;并避…

笔记本电脑销量排名_网友总结京东笔记本销量,联想高居第一,华为表现很出色...

笔记本电脑&#xff0c;还是要看大品牌。网友总结近30天京东笔记本销量&#xff0c;结局让人出乎意料。网友直呼&#xff0c;原来华为笔记本这么强。智能手机的出现&#xff0c;对传统的PC行业造成了一定的影响&#xff0c;但它始终还是无法替代PC的功能。在这个行业中&#xf…

数据结构---二叉排序树

数据结构—二叉排序树 原理&#xff1a;参考趣学数据结构 代码&#xff1a; #include<stdio.h> #include<stdlib.h> typedef struct bstTree {int data;struct bstTree* lchild, *rchild; }bstTree; void createBSTTree(bstTree* & T,int data) {//创建二叉…

研发协同平台持续集成2.0架构演进

在上篇《研发协同平台持续集成实践》一文中我们分享了为什么要做持续集成&#xff0c;技术选型&#xff0c;工作原理以及实践落地。今天我们从架构上来分享一下架构层面的设计和演进。持续集成1.0在最开始设计的过程中&#xff0c;本着一切从需求出发&#xff0c;一切以实现业务…

口袋操作系统_全自动阀口袋包装机的发展

随着全球产业技术的不断发展&#xff0c;包装机行业也出现了产业结构调整的动向&#xff0c;因为全新的全自动阀口袋包装机和全新的包装产品技术问世&#xff0c;那些制作粗糙&#xff0c;能源消耗大&#xff0c;技术相对比较落后的阀口袋包装机也将会被市场一步步淘汰掉&#…

数据结构---二叉搜索树

数据结构—二叉搜索树 原理&#xff1a;参考趣学数据结构 代码&#xff1a; 队列代码&#xff1a; #pragma once #define N 100 #define elemType bstTree* #include<stdlib.h> typedef struct bstTree {int data;struct bstTree* lchild, *rchild; }bstTree; typede…

《ASP.NET Core 微服务实战》-- 读书笔记(第10章)

第 10 章 应用和微服务安全云应用意味着应用运行所在的基础设施无法掌控&#xff0c;因此安全不能再等到事后再考虑&#xff0c;也不能只是检查清单上毫无意义的复选框由于安全与云原生应用密切相关&#xff0c;本章将讨论安全话题&#xff0c;并用示例演示几种保障 ASP.NET Co…