---
# System prepended metadata

title: '[實作] .Net Framework WebAPI 實作 SignalR - 建立環境篇'
tags: [webSockets, Jquery, SignalR, .Net Framework, WebAPI]

---

# [實作] .Net Framework WebAPI 實作 SignalR - 建立環境篇

### :arrow_forward: **綱要**
1. **SignalR 是什麼**
2. **本文環境與專案設定**
3. **基礎 Hub 環境建置 - 程式碼實作**
4. **建立前後端呼叫方法 - 程式碼實作**
5. **實作 SignalR 互動 Web API 功能篇**
---
### 1. SignalR 是什麼
    是一種 ASP.NET 專用套件，提供網頁應用程式擁有 Real-Time 的功能，並能自動切換不同的傳輸方式
- **傳輸模式**：套件內部擁有 webSockets、foreverFrame、serverSentEvents、longPolling 等模式
- **優點**：`ASP.NET` 系統可以直接導入此套件，其支援多元的 Real-Time 傳輸方案
- **隱憂**：前端需要找到適當的 SignalR 套件，否則無法與後端執行 SignalR Real-Time 功能
---
### 2. 本文環境與專案設定
#### (1) 環境
- IDE：VS-2022
- 框架：.Net Framework 4.7.2
- 專案：ASP NET Web API
#### (2) 專案設定
- 前情提要：
本文撰寫方向為前後端分離的中型專案，Web API 負責後端資料庫部分。因為前端之限制條件為不使用 **Jquery**，為了使前端可以介接 **SignalR**，前端採用 **signalr-no-jquery** 的 npm 套件，而 **signalr-no-jquery** 所採用的 **SignalR** 版本為 **2.4.3** (可參考下方參考資料)
- JS 版本：
    - **`jquery-1.6.4.js`** (註：jquery 1.6.4 JS 官方原始碼連結於下方**參考資料**中)
    - **`jquery.signalR-2.4.3.js`**  (註：可於 Nuget 安裝 **Microsoft.AspNet.Signal 2.4.3** 版本)
    
    ![image](https://hackmd.io/_uploads/rJtkZQnmR.png)
---
### 3. 基礎 Hub 環境建置
為了確保後端有架設起 SignalR 的 Hub 環境，本文接續會於 Web API 專案內分別測試後端與前端功能是否都可以正常運作
#### (1) 建立完成專案後，在根目錄下方加入一個 **SignalR Hub Class**，取名為：SRHub.cs
![image](https://hackmd.io/_uploads/H1NETQ5Q0.png)

#### (2) 更新 **Nuget Signalr** 套件 - Microsoft.AspNet.Signal 至 2.4.3 版本
![image](https://hackmd.io/_uploads/H1lEyHq70.png)

#### (3) 可能跳出這個錯誤視窗，看起來是缺乏 OWIN 套件，但仔細一看，都是 zh-Hant 的中文化套件，如果僅是為了中文化，就可以不用理會這個錯誤了(不需仰賴中文化環境)
![image](https://hackmd.io/_uploads/rJ-qT7qmC.png)

#### (4) 在根目錄下面建立一個 **OWIN** 啟動類別，取名為：Startup.cs，此目的為建構 PipeLine，確保 SignalR 進到 API 前，先進行處理
![image](https://hackmd.io/_uploads/ry4QfV5mR.png)
- 並在 Startup.cs 檔案中加入 `app.MapSignalR();`
```csharp=
public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        // 加入這行
        app.MapSignalR();
    }
}
```
#### (5) 接著，建立一個 HTML 頁面，讓用戶端可以透過頁面進入 SignalR Hub
在預設的 HomeController 下面加入一個 `public ActionResult SRPage( )`，並右鍵點選 SRPage( )，**新增檢視**
```csharp=
public class HomeController : Controller
{
    public ActionResult Index()
    {
        ViewBag.Title = "Home Page";

        return View();
    }
    // 加入下面的
    public ActionResult SRPage()
    {
        return View();
    }
    // 加入上面的
}
```
- 選擇 Empty 範本，並取消版面配置頁
![image](https://hackmd.io/_uploads/Hy0BVEcQA.png)

#### (6) 調整此 HTML 頁面，確保 SignalR Hub 可以運行
在檔案總管中找到 View -> Home -> SRPage.cshtml 檔案，將原來的內容刪除並修正為以下的 HTML
```html   
@{
    Layout = null;
}
<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>SRPage</title>
</head>
<body>
    <div class="container">  
    </div>
    @*需要檔案總管中的 Scripts 資料夾中包含 jquery-1.6.4.js 和 jquery.signalR-2.4.3.js 檔案*@
    @*若沒有 jquery-1.6.4.js 請於下方參考資料中前往官方網站，抓下原始碼，自行建立 js 檔案，再放入 Scripts 資料中*@
    <script src="~/Scripts/jquery-1.6.4.js"></script>
    <script src="~/Scripts/jquery.signalR-2.4.3.js"></script>
    <script src="~/signalr/js"></script>
    <script>
        $(function () {
            // sRHub 即為 SignalR Hub Class 的類別名稱，但要特別注意要採用小駝峰(開頭單字小寫)
            var chat = $.connection.sRHub;  

            $.connection.hub.start().done(function () {
                // 如果連線成功，就會在 console 面板顯示出以下訊息
                console.log("BackEnd Server-Side：Signalr Connected");
            });
        });
    </script>
</body>
</html>
```
- 運行專案，並前往 `https://localhost:你自己的port號/Home/SRPage` 路由，打開瀏覽器開發者工具並選擇 console，若顯示 `BackEnd Server-Side：Signalr Connected` 即代表前端頁面已經連上後端的 SignalR Hub 
![image](https://hackmd.io/_uploads/HkSCVN2QA.png)
---
### 4. 前後端 Hub Function 呼叫方式
實作完上面的 Hub 環境建置後，接下來要來嘗試在後端、前端分別加入相關的 Function，讓前後端可以互相呼叫
- **Note**：本文撰寫方向為在 Web API 中自行測試前端與後端環境，因此在本文中，前端將會使用 **jquery** 語法，而實際在**前後端分離**的中型專案中，若前端不使用 **Jquery** 語法，則前端應該使用 **signalr-no-jquery** 套件

#### (1) 呼叫後端方法：於後端 SRHub.cs 檔案中建立後端 SendFromBackend Method
此方法將會於前端被呼叫，並且，前端呼叫方法時，需要傳入一個 String 類別的參數
```csharp=
public class SRHub: Hub
{
    // 加入下面
    public string SendFromBackend(string input)
    {
        return "String Send From Backend，Frontend Input is：" + input;
    }
    // 加入上面
}
```
#### (2) 呼叫後端方法：於前端 SRPage.cshtml 檔案中呼叫後端 SendFromBackend Method
將原來 `connection.hub.start().done` 的區塊，加入呼叫 `SendFromBackend` 後端方法。擴展成以下程式碼
```javascript=
$.connection.hub.start().done(function () {
    // 如果連線成功，就會在 console 面板顯示出以下訊息
    console.log("BackEnd Server-Side：Signalr Connected");
    
    // 呼叫 server 端的方法，如果成功呼叫，就會透過 callback function 帶出 result，就可以把它印出來
    // Note：sendFromBackend 一定要是小駝峰，不然無法成功呼叫
    chat.server.sendFromBackend('I am David').done(function (result) {
        console.log(result)
    }).fail(function (error) {
        console.error('呼叫方法失敗，Error為： ' + error);
    });
});
```
#### (3) 呼叫後端方法：測試結果
運行專案，並前往 `https://localhost:你自己的port號/Home/SRPage` 路由，打開瀏覽器開發者工具並選擇 console，若連線成功，將會顯示 `String Send From Backend，Frontend Input is：I am David` 即代表前端頁面已經連上後端的 SignalR Hub ，並且前端成功呼叫後端所建立的方法
![image](https://hackmd.io/_uploads/Skb7dL27R.png)

#### (4) 呼叫前端方法：於前端 SRPage.cshtml 檔案中建立前端 messageCreateFrontend Function
在前端 HTML 頁面中，將原來 `script` 的區塊，加入 `messageCreateFrontend` 前端方法。擴展成以下程式碼
```html=
<script>
    $(function () {
        var chat = $.connection.sRHub;  

        // 建立前端方法 messageCreateFrontend()，並且需要一個傳入一個參數
        chat.client.messageCreateFrontend = function (message) {
            console.log(message);
        };
    
        $.connection.hub.start().done(function () {
            // ... 省略相關程式碼
            // 建立一個呼叫後端的方法，傳入一個訊息 
            chat.server.callBackendMethod('Call Frontend Function').done(function () {
                // 呼叫完成後端方法後，甚麼事情都不做
            }).fail(function (error) {
                console.error('呼叫方法失敗，Error為： ' + error);
            });
        });
    });
</script>
```
#### (5) 呼叫前端方法：於後端 SRHub.cs 檔案中呼叫 messageCreateFrontend Function
此方法將會於前端被呼叫，並且，前端呼叫方法時，需要傳入一個 String 類別的參數，內部會呼叫前端 `messageCreateFrontend` Function
```csharp=
public class SRHub: Hub
{
    // 加入下面
    public void CallBackendMethod(string input)
    {
        // 把取得的 input 參數，再透過呼叫前端方法傳送給他
        // Note：All 代表對所有連上 Signalr Hub 的使用者都觸發 messageCreateFrontend 前端方法
        Clients.All.messageCreateFrontend(input);
        // 如果僅要針對特定人員觸發 messageCreateFrontend 方法，不能使用 All
    }
    // 加入上面
}
```
#### (6) 呼叫前端方法：測試結果
運行專案，並前往 `https://localhost:你自己的port號/Home/SRPage` 路由，打開瀏覽器開發者工具並選擇 console，若連線成功，將會顯示 `Call Frontend Function` 即代表前端頁面已經連上後端的 SignalR Hub ，並且後端成功呼叫前端所建立的方法
![image](https://hackmd.io/_uploads/S1UbJDn7A.png)

---
### 5. 實作 SignalR 互動 Web API 功能文章
上述完成基礎 Signalr Hub 環境實作後，於後篇文章，將針對用戶群組、Hub 人數統計、Hub 呼叫 Web API 等功能進行說明
- 文章請參考為：**[.Net Framework WebAPI 實作 SignalR - 實作功能篇](https://hackmd.io/@David0799/HJGRRR3QR)**
---
:::info
:bookmark_tabs: **參考資料**
>前端 signalr-no-jquery npm 套件說明：
><https://www.npmjs.com/package/signalr-no-jquery?activeTab=readme>
>
>Jquery 官方 1.6.4 JS 原始碼：
><https://blog.jquery.com/2011/09/12/jquery-1-6-4-released/>
>
>微軟官方 Signalr 介紹網站：
>https://learn.microsoft.com/zh-tw/aspnet/signalr/overview/getting-started/introduction-to-signalr
>
>鐵人幫 SignalR 實作文章：
>https://ithelp.ithome.com.tw/articles/10222931
:::