浏览器中的 .Net Core —— Blazor WebAssembly 初体验
前言
在两年多以前就听闻 Blazor 框架,是 .Net 之父的业余实验性项目,其目的是探索 .Net 与 WebAssembly 的兼容性和应用前景。现在这个项目已经正式成为 Asp.Net Core 框架的一部分,公开了预览版,官方教程也基本写好上线了。就着这个机会,顺便体验一下这个框架用起来如何。
之前在网上搜索 Blazor 的相关信息的时候发现吵得很厉害。前端开发者大多觉得有 Vue 之类的前端 MVVM 框架已经够用,没有 C# 插足的余地。甚至很多 C# 开发者也不知道这个框架的基本工作原理,觉得是把 C# 翻译成 js,翻译之后就变成了类似 Vue 的东西。还有人觉得这是下一个 Flash 或者 Silverlight。毛主席曾经说过:没有调查就没有发言权。对于说这种话的人,我只想说,少刷几分钟抖音快手随便搜下百度都能搞清楚怎么回事,作为 C# 开发者,这都理解不了我是真不知道是怎么学的 C#,难道真是传说中的拖控件一把梭,然后就没然后了?
简单说明下 Blazor WebAssembly 的工作原理。就是在 WebAssembly 框架的基础上,实现了一个 .Net Core Runtime,用一个启动 js 下载相关 dll、初始化 .Net 虚拟机、启动虚拟机运行入口函数,接下来就和一个正常 .Net 程序一样,该怎么运行怎么运行。用 Java 的说法就是在浏览器中运行的 jvm。从此,.Net 跨平台领先 Java 一步,除了 Windows、Linux、MacOS之外,还要加上浏览器。悄悄说一下,浏览器上的运行时实现了 netstandard 2.1,待遇比传统的 .Net Framework 还好。要说缺点就是调试很麻烦,因为整个运行过程和服务器无关,在 VS 下断点也没用,不知道是预览版没做好还是什么原因,顺便导致出问题很难跟踪。还有改了代码要重新编译项目,不能像 MVC 那样改了 cshtml 刷新下浏览器就生效。每次重启调试太耐等了。
正文
目前 Blazor WebAssembly 还不是默认项目模板的一部分,需要自行下载模板才能在 VS 2019 的项目模板里找到,需要的可以移步官方教程。不知道有多少园友知道我有个专门收集各种各种我觉得有趣的示例代码的项目,当然也有很多代码是我自己写的。我就冒出了一个想法,如何把这个项目也集成到我的现有项目中。毕竟创建独立的项目和在现有项目中融合新东西完全是两种感觉,很多组件一旦融合就会各种冲突打架,需要深入了解他们才能知道冲突有没有办法解决,要如何解决。
经过几天的研究,我成功把 Blazor WebAssembly 项目融合进了我的主项目。同时进行了一些改造。主要方法还是先新建一个模板项目,然后对比代码差异,融合代码,补充 nuget 包。接下来简要说明下在现有 Asp.Net Core 项目中增加 Blazor WebAssembly 项目的主要步骤。在我的项目中,/blazor 是 Blazor 根目录,各种修改都配合这个设定,各位请根据自己的情况修改。
客户端
1、新建一个包含 Asp.Net Core 宿主服务器的 Blazor WebAssembly 项目。纯 Blazor WebAssembly 项目发布后可以放到静态文件服务器,宿主服务器也只是当文件服务器用。把客户端项目复制到主项目解决方案中,在 VS 中添加现有项目。如果修改过项目名称和命名空间,请重启 VS,不然可能报错。
2、复制共享项目到主项目的解决方案,修复项目引用。
3、修改 wwwroot/index.html,修改 <head> 标签中的 <base href="/" /> 为 <base href="/blazor" />。
4、在 wwwroot 文件夹新建文件夹 blazor,把 wwwroot 下的其他文件和文件夹放进 wwwroot/blazor 文件夹,避免和主项目路径冲突,同样地,主项目也不能再用 /blazor/xxx 了。
服务端
1、安装 nuget 包 Microsoft.AspNetCore.Blazor.Server,要勾上包括预发行版,不然搜不到。
2、在主项目中引用客户端项目和共享项目。
3、在 Startup.ConfigureServices 中增加代码:
services.AddResponseCompression(opts =>
{
opts.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(
new[] { "application/octet-stream" });
});
4、在 Startup.Configure 中增加 app.UseBlazorDebugging(); 如果只想在开发环境使用,自行增加 if 判断。一般跟 app.UseDeveloperExceptionPage(); 放在一起。
5、在 Startup.Configure 中注册 Blazor 文件,注意类型参数,是客户端项目的 Program 类:
app.UseClientSideBlazorFiles<BlazorApp.Client.Program>();
6、在 Startup.Configure 中检查是否有并补充 app.UseStaticFiles();
7、在 Startup.Configure 中注册路由终结点,注意 "/blazor/{**subPath}" 这一段,表示把 blazor 映射到 /blazor/xxx 去。{**subPath} 这一段是路由终结点参数捕获语法,里面的 subPath 可以乱写,但不能空着不填,不然启动不了。因为 Blazor WebAssembly 启动之后路由都是前端完成的,跟服务器没有任何关系,所以可以乱填。只是要满足系统的语法要求好让服务器能正常启动。
app.UseEndpoints(endpoints =>
{
//以前的 mvc、api 等等各种注册。 //映射 Blazor 客户端终结点
endpoints.MapFallbackToClientSideBlazor<BlazorApp.Client.Program>("/blazor/{**subPath}", "index.html");
});
至此,融合工作完成,可以正常启动项目并访问 /blazor 体验效果了。
效果预览



在两个浏览器(Chrome、Edge by Chromium)分别登录不同账号,分别使用 Blazor WebAssembly SignalR .Net Core Client 和 SignalR Javascript Client 连接 SignalR 服务,手机(Edge Android)再登录另一个账号使用 Blazor WebAssembly SignalR .Net Core Client 连接 SignalR 服务(域名是花生壳域名做 DDNS)。实现跨平台跨终端实时聊天。运行在 Release 发布模式。

结语
总体来说,Blazor 的体验还是很不错的,整体风格和 Asp.Net Core 几乎一摸一样,我看见的一瞬间就感觉非常亲切。依赖注入系统也可以正常使用,只是区别是 Scope 生命周期的实际效果和单例是一样的,因为整个应用就只有一个 Scope,但是 Blazor Server Side 就有区别了,每个 SignalR 连接绑定一个 Scope,掉线重连成功也会恢复到原先的 Scope ,一直连不上太久就不行了,整个服务器进程包含一个单例。所以在注册的时候尽量用 Scope,避免单例成习惯,缓不过来。
Razor 语法也是个神一样的设计,最初是作为 MVC3 的视图引擎推出,在 MVC4 成为默认引擎。好像 MVC5 取消了 aspx 视图引擎支持,.Net Core 彻底取消了和 aspx 有关的一切东西。现在,Razor 又成为了一个前端渲染框架,真是老树发新芽,又是一春。在 html 模板渲染上,我用下来就是 Razor 的 @ 和 Vue 的双花括号语法特别顺手,aspx 那种尖括号语法实在看的头昏脑胀。本来 html 就各种尖括号,还要再来一堆尖括号,VS 高亮都看得头疼,更别说一般文本编辑器打开了,根本看不懂,到底谁和谁是一对?Razor 就特别爽,代码和标记自动识别切换,局部代码块,局部变量,比起 Vue 是有过之而无不及(Vue 的变量作用域师从 js,是真的晕)。
根据目前使用的情况来看,只要不包含涉及系统底层调用的库都可以正常使用,比如和进程、线程、硬件驱动相关、本机 dll 互操作这种。
我在模板项目中,增加了 SignalR 客户端使用示例。也是根据官方教程修改,而且使用的客户端库就是普通 .Net 客户端库,和控制台、桌面程序用是同一套 dll。微软果然神,到底是怎么把网络相关的 API 底层实现神不知鬼不觉地的换掉的。默认注入的 HttpClient 也是 System.Net.Http 命名空间的。
由于网络通信底层实际上是依赖浏览器,所以浏览器会自动把 HttpClient 的请求嫁接到浏览器上,相关的 Headers、Cookies 自然也会自动携带上。所以如果 Blazor 应用和普通网页在同一个域,这些东西实际上会共享。我的身份认证相关功能就是利用这个特点偷懒实现的。如果不在同一个域,最简单实用的方法就是用 IdentityServer4 作为认证服务,客户端引用 nuget 包 IdentityModel,这个包会给 HttpClient 增加一堆用来和 OpenId Connect、OAuth2.0 协议交互的扩展方法,当作两个程序用开放协议配合工作来写就行。用 IdentityModel 扩展获取 Access Token,请求的时候把 Token 加进 HttpClient 的 Headers,当然也可以用 IdentityModel 的扩展来注入,更方便。
对于 SPA 应用来说,状态管理一定是无法绕过的,不过在 Blazor 中,直接用依赖注入来管理状态就可以了。如果需要刷新页面也不丢失状态的话,可以考虑使用 ILocalStorage 服务来持久化状态,或者其他持久化方案也行,反正支持 js 互操作,先随便封装一个应急,等 C# 的原生组件出来了再看怎么办。
与服务器的交互除了常规的 Web Api,还有内部预览阶段的 gRPC-Web,等这东西搞定了,Blazor 极限使用一切二进制数据,那效率不知道能提升多少。Asp.Net Core 3.0 全面支持 HTTP2,Chrome 好像从 70 往后也都支持 HTTP2,gRPC-Web 原生使用 HTTP2 肯定比现在包一层兼容层支持 HTTP1.1 来的好。可以说在浏览器的限制下,能做的应该都差不多。不知道以后浏览器会不会开放线程接口让 WebAssembly 使用内核线程执行计算密集型任务(好像会更方便黑客把浏览器当矿机啊,开放的问题也是多的不行,感觉浏览器就是个黑暗森林,网站服务器要防用户搞破坏,用户也要防网站用脚本搞破坏,这个猜疑链也导致浏览器各种限制,难啊)。
作为一个杂食性开发者,对于 Blazor 与 Vue 的争论这种东西我是无所谓的,只要在我的知识范围内在我能接受的开发复杂度内解决问题,其他的都是浮云。就像邓爷爷说的:实践是检验真理的唯一标准;管他黑猫白猫,抓到耗子就是好猫;这才是我的信条,彻底的实用主义。
啊,C# 这种强类型安全语言进入前端领域有点激动,不注意就说了一大通。被 js 那诡异的对象类型,动态作用域坑的实在是不行,敲键盘的时候心虚不知道会不会莫名其妙突然就出问题,实在是对心脏不好。还是喜欢 C#,什么东西都清晰明了,不埋暗坑,外加 DLR 和 dynamic,真是进可攻、退可守。js 完全没有退路,实在是伤不起。
在最后发布以后才发现 Blazor 聊天进不去,调试正常,试了N多办法都没搞定,最后删除发布文件夹中的所有 dll,关闭 VS,删除 obj、bin 文件夹,重新发布才正常。真是坑爹。
2020-5-26 更新:已经更新到候选版,迁移方法参见博文:Blazor WebAssembly 候选版迁移手记。
转载请完整保留以下内容并在显眼位置标注,未经授权删除以下内容进行转载盗用的,保留追究法律责任的权利!
本文地址:https://www.cnblogs.com/coredx/p/12342936.html
完整源代码:Github
里面有各种小东西,这只是其中之一,不嫌弃的话可以Star一下。
浏览器中的 .Net Core —— Blazor WebAssembly 初体验的更多相关文章
- ASP.NET Core Blazor Webassembly 之 路由
web最精妙的设计就是通过url把多个页面串联起来,并且可以互相跳转.我们开发系统的时候总是需要使用路由来实现页面间的跳转.传统的web开发主要是使用a标签或者是服务端redirect来跳转.那今天来 ...
- ASP.NET Core Blazor Webassembly 之 数据绑定
上一次我们学习了Blazor组件相关的知识(Asp.net Core Blazor Webassembly - 组件).这次继续学习Blazor的数据绑定相关的知识.当代前端框架都离不开数据绑定技术. ...
- .net core安装及初体验
.net core安装及初体验 .net core 作为微软的新一代技术,在开发跨平台.微服务等方面有很大的优势,也更贴近现代的编码习惯.在2.0版发布很久以后,近期终于决定进行学习和体验. 安装 作 ...
- [Asp.Net Core] Blazor WebAssembly - 工程向 - 如何在欢迎页面里, 预先加载wasm所需的文件
前言, Blazor Assembly 需要最少 1.9M 的下载量. ( Blazor WebAssembly 船新项目下载量测试 , 仅供参考. ) 随着程序越来越复杂, 引用的东西越来越多, ...
- ASP.NET Core Blazor WebAssembly实现一个简单的TODO List
基于blazor实现的一个简单的TODO List 最近看到一些大佬都开始关注blazor,我也想学习一下.做了一个小的demo,todolist,仅是一个小示例,参考此vue项目的实现http:// ...
- ASP.NET Core Blazor Webassembly 之 渐进式应用(PWA)
Blazor支持渐进式应用开发也就是PWA.使用PWA模式可以使得web应用有原生应用般的体验. 什么是PWA PWA应用是指那些使用指定技术和标准模式来开发的web应用,这将同时赋予它们web应用和 ...
- ASP.NET Core Blazor Webassembly 之 组件
关于组件 现在前端几大轮子全面组件化.组件让我们可以对常用的功能进行封装,以便复用.组件这东西对于搞.NET的同学其实并不陌生,以前ASP.NET WebForm的用户控件其实也是一种组件.它封装ht ...
- ASP.NET Core Blazor WebAssembly 之 .NET JavaScript互调
Blazor WebAssembly可以在浏览器上跑C#代码,但是很多时候显然还是需要跟JavaScript打交道.比如操作dom,当然跟angular.vue一样不提倡直接操作dom:比如浏览器的后 ...
- (一) .net core 2.0 初体验
1..net core 2.0环境 .net core 下载地址:https://www.microsoft.com/net/core#windowscmd 问题一:提示[Failed to load ...
随机推荐
- 输入n个学生,并且输入成绩,判断是否偏科
H学校的领导主任决定分析一下今年所有N名学生的考试成绩,从中找出偏科的学生,考试成绩包含语文,数学,英语三门课程的分数,已知偏科的定义是:某一门课程的分数大于等于90,并且另外两门的分数小于等于70. ...
- Scala实践8
1.1继承类 使用extends关键字,在定义中给出子类需要而超类没有的字段和方法,或者重写超类的方法. class Person { var name = "zhangsan" ...
- 小白学 Python 爬虫(42):春节去哪里玩(系列终篇)
人生苦短,我用 Python 前文传送门: 小白学 Python 爬虫(1):开篇 小白学 Python 爬虫(2):前置准备(一)基本类库的安装 小白学 Python 爬虫(3):前置准备(二)Li ...
- 【PCIE-2】---PCIE配置空间及访问方式简介
对新手来说,第一步了解PCIE的相关基本概念,第二步了解PCIE配置空间,第三步深入研究PCIE设备枚举方式.本章主要总结第二步的PCIE配置空间 按照国际惯例,先提问题: 1. 什么是PCIE的配置 ...
- sql中,case when的几种写法
Province = CASE WHEN DCCity = '商丘' THEN '河南' WHEN DCCity <> '商丘' THEN '非河南' END, case ISNeed w ...
- 元素定位工具Weditor的使用
(1).安装:pip install --pre --upgrade weditor 安装成功 (2).启动python -m weditor
- 聊聊HTTP请求那一些事_HttpWebRequest_一篇就够了
最近工作比较忙,很久没有写东西了,今天抽点时间整体一下最近工作的一个知识点小结.http请求对我们来说一点都不模式,程序员的我们有可能天天就是和这一些打交道.无论是BS架构的程序,前后端的数据交互, ...
- jenkins 配置ssh密钥登录
1.找到一台服务器执行 ssh-keygen -t rsa 会在目录/root/.ssh生成id_rsa私钥.id_rsa.pub公钥,将公钥的内容写入到同目录下的authorized_keys文件( ...
- 实验三:在eNSP上进行Hybrid链路类型端口实验
1.配置图 2.配置命令 LSW1的命令配置如下: <Huawei>system-view 进入特权模式 [Huawei]vlan batch 2 3 99 创建vlan2.vlan3.v ...
- 实验二:在Cisco Packet Tracer模拟器上进行Trunk+Access端口混合模式实验
1.配置图 2.配置命令 Switch0的VLAN配置如下: 查看Switch0的vlan配置如下: Switch0的Trunk端口配置如下: Switch1的VLAN配置如下: 查看Switch1的 ...