使用SignalR構建聊天應用程式
SignalR是面向ASP.NET開發人員的開源庫。 這等效於Socket.IO用於Node.js(如果需要,您可以在Stack Overflow上進行比較 )。 SignalR可用於為您的應用程式提供實時Web功能。 通常,如果您喜歡Ember和JavaScript,則可能會傾向於選擇Socket.IO並堅持使用JavaScript。 我選擇SignalR的原因之一是它具有更擴充套件的文件和一些參考資源。 此外,您可以免費獲得ASP.NET world的所有好處。
在本文中,我將向您展示如何使用SignalR構建簡單的聊天應用程式。 如果尚未完成,建議您閱讀上一篇名為“ 使用Socket.IO的聊天應用程式 ”,以更全面地瞭解這些主題,然後比較兩種方法的優缺點。
ember-cli入門
我們將首先建立一個新的Ember應用程式,然後使用ember-cli 。 首先,讓我們安裝一些依賴項:
$ ember new chatr
$ ember install semantic-ui-ember
在這裡,我們將安裝語義UI ,這是一個開發框架,可以使用人類友好的HTML幫助建立美觀,響應式的佈局。
它與Bootstrap非常相似,它將幫助我們確定網站的佈局和主題。 完成後,我們必須將其匯入到應用程式中。
現在, Brocfile.js
新增到Brocfile.js
檔案中:
app.import('bower_components/semantic-ui/dist/semantic.css');
app.import('bower_components/semantic-ui/dist/semantic.js');
現在,我們準備建立路線並新增一些模板。 為此,請執行以下命令:
$ ember g route chat
這將建立我們的Ember路線app/routes/chat.js
和模板app/templates/chat.hbs
。 在向模板新增任何內容之前,我們將使用一些Ember元件來封裝模板並使它們可重用。 讓我們從chat-room
元件開始:
$ ember g component chat-room
$ ember g component chat-userlist
$ ember g component chat-area
$ ember g component chat-useritem
如您所見,我們有很多元件。 每個元件都有一個關聯的模板檔案( app/templates/components/chat-room.hbs
)和一個Ember元件指令碼檔案( app/components/chat-room.js
)。 這樣,我們可以隔離聊天功能,從而易於測試和推理。 此時,我們可以將chat-room
新增到我們的聊天路由中:
{{#chat-room
users=room.users
messages=room.messages
topic=room.topic
onSendChat="sendChat"}}{{/chat-room}}
users
, messages
和topic
是我們傳遞給元件的資料,而onSendChat
是由元件觸發的操作。 如果您想加深這些概念,可以閱讀Ember指南以獲得更多資訊 。
最後,我們需要一個Ember控制器(以處理聊天路由的邏輯)和一些Ember模型。 為此,請執行以下命令:
$ ember g controller chat
$ ember g model chat-room
$ ember g model chat-user
$ ember g model chat-message
模型是從Ember.Object
繼承的有用類。 他們將儲存我們的資料並提供與模板的資料繫結。 控制器執行相同的操作,控制器裝飾模型並也可以處理使用者操作。
開啟app/controllers/chat.js
檔案,並向其中新增以下程式碼:
export default Ember.Controller.extend({
initRoom: function(users, messages, topic) {
var room = Room.create({
users: users,
messages: messages,
topic: topic
});
this.set('room', room);
},
addMessage: function(msg) {
var room = this.get('room');
room.get('messages').addObject(msg);
},
userJoin: function(user) {
var room = this.get('room');
room.get('users').addObject(user);
},
actions: {
sendChat: function(msg) {
// use these methods here to test if they are working
//this.addMessage('ME', msg);
//this.userJoin(msg);
}
}
});
addMessage()
和userJoin()
是在需要新增新聊天訊息或新使用者時可以呼叫的輔助方法。 sendChat
是使用者要傳送訊息時觸發的動作處理程式。 initRoom()
是用於設定繫結的建構函式。 您可以在我們的聊天路線的setupController()
掛鉤中使用空資料呼叫它,以測試一切是否正常執行。
現在,通過新增以下程式碼來編輯app/routes/chat.js
檔案:
export default Ember.Route.extend({
setupController: function(controller) {
// use this method to test everything is working when data is bound.
//controller.initRoom([],[], 'hello world');
}
});
使用SignalR構建伺服器端
我們在使用SignalR時需要使用的另一個有用的工具是Visual Studio 。 下載之後,開啟它並建立一個新的Empty Web Application
專案,並使用“程式包管理器控制檯”安裝所需的程式包:
Install-Package Microsoft.AspNet.Signalr
該命令將安裝SignalR及其所有依賴項,包括“ Microsoft.Owin”。 然後,我們繼續建立OWIN啟動類以引導我們的伺服器。 為此,我們將在App_Start/Startup.cs
檔案中包含以下程式碼:
public class Startup {
public void Configuration(IAppBuilder app) {
app.MapSignalR();
}
}
就是執行基於OWIN的Web伺服器。 我們將SignalR中介軟體新增到OWIN,但是您可以根據需要新增其他中介軟體(例如身份驗證或Web API)。 現在可以通過按F5鍵來啟動我們的SignalR應用程式。 我們沒有託管任何資料,因此瀏覽器不會顯示任何對我們有用的資訊。 該JavaScript程式碼由SignalR動態生成,並可供我們的Ember應用程式使用。 它為我們提供了JavaScript方法,這些方法將進一步在伺服器端呼叫方法。
建立大廳中心
集線器類用於與客戶端通訊。 它可以在客戶端上呼叫方法,並定義從客戶端呼叫的方法。 每當新客戶端連線或對伺服器進行方法呼叫時,SignalR都會建立一個新的Hub類。 現在,讓我們看看如何建立大廳Hub:
public class Lobby : Hub {
private IChatRRepository _repository;
public Lobby(IChatRRepository repository) {
_repository = repository;
}
public void Join(string name) {
ChatUser currentUser = new ChatUser(name, Context.ConnectionId);
_repository.AddUser(currentUser);
var users = _repository.Users.ToList();
var topic = "Welcome to EmberJS on SignalR";
Clients.Caller.lobbyEntered(topic, users);
}
public void SendChat(string msg) {
ChatUser user = _repository.GetUserById(Context.ConnectionId);
Clients.All.chatSent(user.Name, msg);
}
public override Task OnDisconnected(bool stopCalled) {
_repository.RemoveUser(Context.ConnectionId);
return base.OnDisconnected(stopCalled);
}
}
根據每個客戶端請求,SignalR例項化一個新的Hub例項。 集線器不維護任何客戶端狀態。 因此,我們需要某種資料庫來跟蹤客戶端狀態。 IChatRepository
介面通過提供諸如AddUser()
, RemoveUser()
和Users()
來檢索所有使用者,從而為我們提供了所需的狀態。 可以從客戶端呼叫Hub方法,並且Hub類可以使用Clients
屬性呼叫客戶端方法。
在下面,您可以找到一個列表,該列表指定哪些客戶端將接收該方法呼叫:
-
Clients.All.someMethod()
:所有連線的客戶端 -
Clients.Caller.someMethod()
:僅主叫客戶端 -
Clients.Others.someMethod()
:除呼叫Clients.Others.someMethod()
所有客戶端 -
Clients.Client(Context.ConnectionId).someMethod()
:特定的客戶端
如您所見,它具有直觀的API。 someMethod()
是動態排程的,因此可以是任何東西。 有關Hubs API的更多資訊,請參閱指南 。
回到我們的示例,我們有兩個Hub方法: Join()
和SendChat()
。 客戶端連線時,它將使用username
呼叫Join()
。 我們將使用者新增到我們的倉庫和呼叫lobbyEntered()
的方法Clients.Caller
。
客戶端傳送聊天訊息時,將呼叫SendChat()
方法。 我們從儲存庫中檢索呼叫方,並通過呼叫Clients.All.chatSent()
方法將訊息廣播到所有連線的客戶端。 反過來,它在所有連線的客戶端上呼叫chatSent()
方法。
最後,有些方法(例如OnConnected()
和OnDisconnected()
可以重寫,以便在使用者連線/斷開連線時得到通知。 有關SignalR API的更多資訊,請參閱《 SignalR指南》 。
使用Ember在客戶端上設定SignalR
現在,讓我們回到客戶端應用程式並整合SignalR。 首先,使用Bower安裝SignalR:
$ bower install signalr --save
接下來,將其匯入我們的應用程式。 為此,請再次開啟Brocfile.js
檔案並新增以下行:
app.import('bower_components/signalr/jquery.signalR.js');
最後,在您的app/index.html
頁面中包含http://localhost:<port>/signalr/hubs
指令碼:
<script src="assets/vendor.js"></script>
<script src="http://localhost:53246/signalr/hubs"></script>
<script src="assets/chatr.js"></script>
在此階段中,請注意元素的順序,這很重要,因為SignalR是作為jQuery外掛匯出的。 因此,我們需要首先包含jQuery(在assets/vendor.js
內部),然後在/signalr/hubs
包含動態指令碼檔案,最後在它之上包含我們的應用程式( assets/chatr.js
)。
使用Ember初始化程式將SignalR注入聊天路由
當我們的應用程式啟動時,我們必須建立一個SignalR連線,然後在我們的控制器中使用它。 這裡的架構取決於您。 我們將使用Ember初始化程式將SignalR注入到我們的路由中。 讓我們看看如何使用先前引用的ember-cli建立它。
$ ember g initializer signalr
現在讓我們初始化SignalR並將其注入到我們的路由中。 以下程式碼片段進入app/initializer/signalr.js
檔案:
import SignalRConnection from 'chatr/utils/net/chatr-realtime';
export function initialize(container, application) {
var realtime = new SignalRConnection('http:/localhost:<port>/signalr');
application.register('realtime:signalr', realtime, { instantiate: false });
application.inject('route:chat', 'signalr', 'realtime:signalr');
}
SignalRConnection
是SignalRConnection
的包裝類,它肯定會使我們的生活更輕鬆。 我們建立它,並使用依賴注入將其注入聊天路由。 同樣, 如果您需要更多資訊,請參閱完整的Ember指南 。
您可以檢出SignalRConnection類以瞭解其實現方式。 這裡有兩種有趣的方法:
configureHubs(ctrl) {
this.OnLobby = new LobbyCallbacks(this, ctrl);
var lobby = Ember.$.connection.lobby;
lobby.client['lobbyEntered'] = this.OnLobby['lobbyEntered'];
lobby.client['chatSent'] = this.OnLobby['chatSent'];
}
在開始SignalR連線之前,我們需要設定伺服器可以在大廳集線器上呼叫的客戶端方法。 Ember.$.connection
是我們的SignalR連線,而Ember.$.connection.lobby
是我們的大廳樞紐。 這些是在動態生成的SignalR程式碼中定義的。 我們通過將方法分配給我們的大廳中心上的client
屬性(即Ember.$.connection.lobby.client
屬性)來設定方法。
在我們的示例中,它們在LobbyCallbacks類中定義:
start(name) {
var self = this;
var hub = Ember.$.connection.hub;
hub.error(function(reason) {
console.log('connection error: ' + reason);
});
return hub.start({
withCredentials: false
}).then(function() {
console.log('connected');
Ember.$.connection.lobby.server.join(name);
});
}
定義客戶端方法後,我們可以使用此方法啟動應用程式。 首先,我們獲得對Ember.$.connection.hub
的引用,在這裡我們設定error
鉤子以獲取有關任何連線錯誤的通知。 最後,我們執行一個start
呼叫以啟動連線,並有一個諾言。
連線後,我們稱為Ember.$.connection.lobby.server.join()
。 此方法將在伺服器端Lobby
Hub上呼叫Join()
方法。 有關SignalR客戶端API的更多資訊,請訪問SignalR指南 。
與CORS打交道
此時,我們可以從Ember應用程式連線到伺服器。 但是,我們可能會遇到一些瀏覽器錯誤,如下所示:
XMLHttpRequest cannot load http://localhost:53246/signalr/negotiate?clientProtocol=1.5&connectionData=%5B%7B%22name%22%3A%22lobby%22%7D%5D&_=1433597715652. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://192.168.56.103:4200' is thus, so not allowed access.
此錯誤可能是由於您的伺服器和客戶端位於不同的域中引起的。 您需要允許伺服器上的CORS
繞過它。 因此,讓我們在Visual Studio軟體包管理器控制檯上安裝軟體包:
Install-Package Microsoft.Owin.Cors
然後,配置Owin中介軟體以允許跨域請求(編輯App_Start/Startup.cs
檔案):
public void Configuration(IAppBuilder app) {
app.Map("/signalr", map =>
{
var corsPolicy = new CorsPolicy
{
AllowAnyHeader = true,
AllowAnyMethod = true
};
// Add the domain where your client is hosted on.
corsPolicy.Origins.Add("http://192.168.56.103:4200");
map.UseCors(new CorsOptions
{
PolicyProvider = new CorsPolicyProvider {
PolicyResolver =
r => Task.FromResult(corsPolicy)
}
});
map.RunSignalR(config);
});
}
結論
在本文中,我們已經看到了如何通過幾個簡單的步驟將SignalR與Ember粘合在一起並建立聊天應用程式。 如果您想看到它的實際效果,可以在chatembar上觀看一個有趣的現場演示 ,如果您想動手做專案,則可以在GitHub上找到完整的原始碼,包括客戶端和伺服器端 。 此外,您可以參考另一個使用SignalR的協作聊天應用程式的出色示例,稱為JabbR 。
我強烈建議您加深一些要點,我沒有機會在本文中介紹:OWIN和身份驗證。 好訊息是SignalR不需要任何特殊的授權,因為它可以與現有的ASP.NET身份驗證解決方案(例如ASP.NET Identity)一起使用。
如果您想了解更多,這裡有一些有關Owin,SignalR和ASP.NET Identity的有用資源:
- 使用ASP.NET Web API 2,Owin和身份的基於令牌的身份驗證
- 向現有的ASP.NET MVC應用程式中新增最少的OWIN身份驗證
- ASP.NET Identity推薦資源
- 這是Owin Stuff的事嗎?
- Katana專案入門
- Nancy:輕便,低禮儀的框架,用於在.Net和Mono上構建基於HTTP的服務
From: https://www.sitepoint.com/building-chat-application-signalr/
相關文章
- 使用Rust和WebAssembly構建Web應用程式RustWeb
- 使用微服務構建現代應用程式微服務
- 使用 webpack 構建應用Web
- 使用汽車應用庫構建應用
- 使用 SCons 代替 Makefile 快速構建應用程式
- 使用 LangChain 構建聊天機器人LangChain機器人
- 使用React.js和應用快取構建快速同步應用程式ReactJS快取
- 使用SvelteKit構建實時websocket應用程式 - IngestWeb
- Judo:使用無程式碼構建原生應用體驗
- 【譯】如何使用PHP快速構建命令列應用程式PHP命令列
- 使用 Oracle XML Publisher 構建線上報表應用程式OracleXML
- 使用 nuxi build 命令構建你的 Nuxt 應用程式UXUI
- JavaFX桌面應用-構建程式框架Java框架
- 使用webpack構建多頁應用Web
- 使用Golang快速構建WEB應用GolangWeb
- WebSocket+Netty構建web聊天程式WebNetty
- 五、Spring Web應用程式構建SpringWeb
- 如何構建 Android MVVM 應用程式AndroidMVVM
- 構建應用程式的正確方法
- 「譯」使用 Node 構建命令列應用命令列
- 使用 Cloudflare 構建 Web3 應用CloudWeb
- 使用 WebSocket 構建實時性應用Web
- 使用AngularJS構建大型Web應用AngularJSWeb
- 使用 IBM Bluemix 構建,部署和管理自定義應用程式IBM
- 使用 Docker 和 Elasticsearch 構建一個全文搜尋應用程式DockerElasticsearch
- 使用Backbone構建精美應用的7條建議
- 構建 API 應用API
- 使用JHipster構建Spring和React構建電子商務應用程式原始碼 -DEVSpringReact原始碼dev
- iTunes構建版本 獲取不到應用程式
- 如何基於 Redis 構建應用程式元件Redis元件
- WebSphere Business Events 構建業務事件應用程式Web事件
- 使用Angular與TypeScript構建Electron應用(六)AngularTypeScript
- 使用Angular與TypeScript構建Electron應用(一)AngularTypeScript
- 使用Java和Reactive Streams構建流式應用JavaReact
- 使用 Micronaut和OpenFaaS 構建無伺服器Java 應用程式 - openvalue伺服器Java
- 我們是如何使用 Electron 構建 Linux 桌面應用程式的Linux
- 如何使用JavaScript UI控制元件(WijmoJS)構建Electron應用程式JavaScriptUI控制元件JS
- 使用Kotlin構建更適合Android的MVVM應用程式KotlinAndroidMVVM