瀏覽器中的 .Net Core —— Blazor WebAssembly 初體驗

来源:https://www.cnblogs.com/coredx/archive/2020/02/22/12342936.html
-Advertisement-
Play Games

前言 在兩年多以前就聽聞 Blazor 框架,是 .Net 之父的業餘實驗性項目,其目的是探索 .Net 與 WebAssembly 的相容性和應用前景。現在這個項目已經正式成為 Asp.Net Core 框架的一部分,公開了預覽版,官方教程也基本寫好上線了。就著這個機會,順便體驗一下這個框架用起來 ...


前言

       在兩年多以前就聽聞 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 中增加代碼:

1 services.AddResponseCompression(opts =>
2 {
3     opts.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(
4         new[] { "application/octet-stream" });
5 });

       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 啟動之後路由都是前端完成的,跟伺服器沒有任何關係,所以可以亂填。只是要滿足系統的語法要求好讓伺服器能正常啟動。

1 app.UseEndpoints(endpoints =>
2 {
3     //以前的 mvc、api 等等各種註冊。
4 
5     //映射 Blazor 客戶端終結點
6     endpoints.MapFallbackToClientSideBlazor<BlazorApp.Client.Program>("/blazor/{**subPath}", "index.html");
7 });

       至此,融合工作完成,可以正常啟動項目並訪問 /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 文件夾,重新發佈才正常。真是坑爹。

 

       轉載請完整保留以下內容併在顯眼位置標註,未經授權刪除以下內容進行轉載盜用的,保留追究法律責任的權利!

  本文地址:https://www.cnblogs.com/coredx/p/12342936.html

  完整源代碼:Github

  裡面有各種小東西,這隻是其中之一,不嫌棄的話可以Star一下。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • Nginx 其實就是一款輕量級的 Web 伺服器、反向代理伺服器,由於它的記憶體占用少,啟動極快,高併發能力強,在互聯網項目中廣泛應用。 那麼你可能會問了:“不是說 Nginx 嗎?怎麼又扯出來一個 Web 伺服器呢?啥是伺服器?”。彆著急,在學習 Nginx 之前你還真得知道什麼是伺服器這個概念,下 ...
  • R語言主要用於統計,因此引入了向量這個概念將更好地進行統計計算,在其他無法引入向量的語言當中則會使用迴圈來計算一些大規模的數據,在R語言當中則不需要,下麵我們來看看R語言當中向量的具體用法吧! 首先,如果我們把x作為一個向量,將其賦值為擁有五個元素的向量,代碼如下: > x <- c(1,2,3,4 ...
  • `爬蟲呢有時候數據方便有時候登入獲得cookies,以及獲取他存緩存中的數據` 一.獲取緩存中的數據其實很簡單js註入就好了 ...
  • 這兩天複習了下Request以及Response部分的內容。 主要內容 1. HTTP協議:響應消息 2. Request對象 3. Response對象 4. ServletContext對象 HTTP: 概念:Hyper Text Transfer Protocol 超文本傳輸協議 傳輸協議:定 ...
  • 記錄LINQ學習過程。 概要 LINQ是一種“語言集成”的查詢表達式,使用LINQ可以智能提示和進行類型檢查。C#里可以編寫的LINQ查詢有SQL資料庫、XML文檔、ADO.NET數據集、支持IEnumerable和IEnumerable的對象。使用LINQ,可以簡單對數據源進行分組、排序、篩選。有 ...
  • WPF允許使用Image元素顯示點陣圖。然而,按這種方法顯示圖片的方法完全是單向的。應用程式使用現成的點陣圖,讀取問題,併在視窗中顯示點陣圖。就其本身而言,Image元素沒有提供創建和編輯點陣圖信息的方法。 這正是WriteableBitmap類的用武之地。該類繼承自BitmapSource,BitmapS ...
  • 哈嘍..大家好 很久沒有更新了,今天就來一篇最近開發用到的功能,那就是中英文切換,這個實際上也不是高大上,先說一下原理,在.NET Core框架中給我們提供了全球化的類,叫做Localization,其官方的文檔地址傳送門。 在我的項目中,我是這樣操作的,你想用別的方式,也可以看文檔自己去搞。這個已 ...
  • .NET web開發者在開發過程中,一定都踩過的坑,明明修改了js文件,可是部署到生產環境,客戶反饋說:“還是報錯啊”。。然後一臉懵逼的去伺服器上看文件,確實已經更新了。有經驗的coder可能就想到了,肯定是客戶端瀏覽器緩存搞的鬼。 此時會告訴客戶,請Crtl+F5刷新一下,這時,客戶會說:“Ctr ...
一周排行
    -Advertisement-
    Play Games
  • 概述:在C#中,++i和i++都是自增運算符,其中++i先增加值再返回,而i++先返回值再增加。應用場景根據需求選擇,首碼適合先增後用,尾碼適合先用後增。詳細示例提供清晰的代碼演示這兩者的操作時機和實際應用。 在C#中,++i 和 i++ 都是自增運算符,但它們在操作上有細微的差異,主要體現在操作的 ...
  • 上次發佈了:Taurus.MVC 性能壓力測試(ap 壓測 和 linux 下wrk 壓測):.NET Core 版本,今天計劃準備壓測一下 .NET 版本,來測試並記錄一下 Taurus.MVC 框架在 .NET 版本的性能,以便後續持續優化改進。 為了方便對比,本文章的電腦環境和測試思路,儘量和... ...
  • .NET WebAPI作為一種構建RESTful服務的強大工具,為開發者提供了便捷的方式來定義、處理HTTP請求並返迴響應。在設計API介面時,正確地接收和解析客戶端發送的數據至關重要。.NET WebAPI提供了一系列特性,如[FromRoute]、[FromQuery]和[FromBody],用 ...
  • 原因:我之所以想做這個項目,是因為在之前查找關於C#/WPF相關資料時,我發現講解圖像濾鏡的資源非常稀缺。此外,我註意到許多現有的開源庫主要基於CPU進行圖像渲染。這種方式在處理大量圖像時,會導致CPU的渲染負擔過重。因此,我將在下文中介紹如何通過GPU渲染來有效實現圖像的各種濾鏡效果。 生成的效果 ...
  • 引言 上一章我們介紹了在xUnit單元測試中用xUnit.DependencyInject來使用依賴註入,上一章我們的Sample.Repository倉儲層有一個批量註入的介面沒有做單元測試,今天用這個示例來演示一下如何用Bogus創建模擬數據 ,和 EFCore 的種子數據生成 Bogus 的優 ...
  • 一、前言 在自己的項目中,涉及到實時心率曲線的繪製,項目上的曲線繪製,一般很難找到能直接用的第三方庫,而且有些還是定製化的功能,所以還是自己繪製比較方便。很多人一聽到自己畫就害怕,感覺很難,今天就分享一個完整的實時心率數據繪製心率曲線圖的例子;之前的博客也分享給DrawingVisual繪製曲線的方 ...
  • 如果你在自定義的 Main 方法中直接使用 App 類並啟動應用程式,但發現 App.xaml 中定義的資源沒有被正確載入,那麼問題可能在於如何正確配置 App.xaml 與你的 App 類的交互。 確保 App.xaml 文件中的 x:Class 屬性正確指向你的 App 類。這樣,當你創建 Ap ...
  • 一:背景 1. 講故事 上個月有個朋友在微信上找到我,說他們的軟體在客戶那邊隔幾天就要崩潰一次,一直都沒有找到原因,讓我幫忙看下怎麼回事,確實工控類的軟體環境複雜難搞,朋友手上有一個崩潰的dump,剛好丟給我來分析一下。 二:WinDbg分析 1. 程式為什麼會崩潰 windbg 有一個厲害之處在於 ...
  • 前言 .NET生態中有許多依賴註入容器。在大多數情況下,微軟提供的內置容器在易用性和性能方面都非常優秀。外加ASP.NET Core預設使用內置容器,使用很方便。 但是筆者在使用中一直有一個頭疼的問題:服務工廠無法提供請求的服務類型相關的信息。這在一般情況下並沒有影響,但是內置容器支持註冊開放泛型服 ...
  • 一、前言 在項目開發過程中,DataGrid是經常使用到的一個數據展示控制項,而通常表格的最後一列是作為操作列存在,比如會有編輯、刪除等功能按鈕。但WPF的原始DataGrid中,預設只支持固定左側列,這跟大家習慣性操作列放最後不符,今天就來介紹一種簡單的方式實現固定右側列。(這裡的實現方式參考的大佬 ...