用SignalR 2.0開發客服系統 續集[系列6:使用自己的連接ID]

前言

老規矩,前言~,在此先道個歉,之前的1-5對很多細節問題都講的不是很詳細,也有很多人在QQ或者博客問我一些問題

所以,特開了這個續集.. - -, 講一些大家在開發中遇到的問題和一些解決方案,今天就來說說經常被問到的,如何使用自己定義的連接ID.

之前我們說過,Signalr提供了唯一的連接ID 獲取方法:Context.ConnectionId,

那麼怎麼自己定義這個東西呢? (廢話一堆 - - ,),進入主題:

首先,其實在Signalr的前期版本是可以直接自定義Context.ConnectionId,

使用老版本的可以自行查看IConnectionIdGenerator, IConnectionIdFactory 這兩個接口.

所以特意說明一下,本博客這裏的代碼,只適用於Signalr2.0以上版本

 

 

代碼環境

開發工具:VS2013   數據庫:SQL2008 R2   SignalR版本:2.2

 

 

正文開始

其實在2.0的版本中,SignalR團隊爲了安全性,已經完全去除了自定義Context.ConnectionId的接口,但是相應的開放了相對安全的IUserIdProvider

廢話不多說,直接上代碼:

 

首先帳戶登陸的代碼:

其實就是很傳統的登陸代碼..把一些用戶信息寫入到Cookie中而已.黃色爲重點

複製代碼
    public class UserController : ApiController
    {
        [HttpGet]
        public object Login(string name,string pwd)
        {
           UserInfoBLL bll = new UserInfoBLL();
           if (CacheHelper.Get(name) == null)
           {
               var userinfo = bll.LoginUser(name, pwd);
              
               if (userinfo != null)
               {

                   var context = HttpContext.Current;
                   //帳戶信息寫入Cookie,自行加密
                   context.Response.Cookies.Add(new HttpCookie(UserEnum.INFO) { Value = JsonConvert.SerializeObject(userinfo) });
//唯一的登陸ID,作爲連接ID context.Response.Cookies.Add(new HttpCookie(UserEnum.SignalRID) { Value = userinfo.LoginName });

return new { State=true,Message="登陸成功!"}; } else { return new { State=false,Message="帳戶或密碼輸入錯誤!"}; } } else { return new { State=false,Message="該帳戶已經登陸!"}; } } }
複製代碼

 

接下來實現IUserIdProvider:

複製代碼
    public class MyUserFactory : IUserIdProvider
    {

        public string GetUserId(IRequest request)
        {
            if (request.GetHttpContext().Request.Cookies[UserEnum.SignalRID] != null)
            {
                return request.GetHttpContext().Request.Cookies[UserEnum.SignalRID].Value;
            }
            return "";
           // return Guid.NewGuid().ToString();
        }
    }
複製代碼

以上代碼是創建一個MyUserFactory類,繼承自IUserIdProvider,實現IUserIdProvider的抽象方法GetUserId

這裏的ID我們從Cookies中獲取,細心的人應該已經發現了,有個IRequest的參數,所以原則上你可以使用IRequest的各種屬性比如QS..你隨意..(注:Session暫時無法使用,原因未知)

 

接下來,重點來了..

在Starup中,把我們自定義的MyUserFactory注入到回話設置中..

代碼如下(黃色爲重點):

複製代碼
 public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            // 有關如何配置應用程序的詳細信息,請訪問 http://go.microsoft.com/fwlink/?LinkID=316888

            //重點,將MyUserFactory注入
            var userIdProvider = new MyUserFactory();
            GlobalHost.DependencyResolver.Register(typeof(IUserIdProvider), () => userIdProvider);

//設置Webapi var config = new HttpConfiguration(); config.Routes.MapHttpRoute(name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional }); System.Web.HttpContext.Current.SetSessionStateBehavior(System.Web.SessionState.SessionStateBehavior.Required); app.UseWebApi(config); app.MapSignalR(); } }
複製代碼

 

接下來在Hub中添加代碼如下:

複製代碼
            /// <summary>
            /// 獲取連接ID,你可以寫成自己的擴展方法,或設置成屬性,自行定義
            /// </summary>
            /// <returns></returns>
            public string GetSignalrID()
            {
                if (Context.Request.GetHttpContext().Request.Cookies[UserEnum.SignalRID] != null)
                {
                    return Context.Request.GetHttpContext().Request.Cookies[UserEnum.SignalRID].Value;
                }
                return "";
            }
            //編寫發送信息的方法
            public void SendMessage(string message)
            {

                string id = Context.ConnectionId;
                string username = Context.User.Identity.Name;
                var userinfo = JsonConvert.DeserializeObject<UserInfo>(Context.Request.GetHttpContext().Request.Cookies[UserEnum.INFO].Value);
                 var Message = new
                        {
                            name = userinfo.UserName,
                            loadname = userinfo.LoginName,
                            picurl = userinfo.UserPicUrl,
                            time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
                            message = message
                        };
                       
                        Clients.User(GetSignalrID()).broadcastMessage(Message);
            }
複製代碼

說明:重點是標黃色的地方,看過我之前文章的都知道,之前我們的對指定連接對象發送數據,寫法爲: Clients.Client("連接ID").客戶端方法,

這裏我們換成了Clients.User("自定義ID"),這樣就完成了整個使用自己的連接ID的替換工作.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章