SIGNALR implementation of real-time web chat instance code

Source: Internet
Author: User
This article mainly introduces the ASP. NET SIGNALR to do real-time web chat instance code, has certain reference value, the interested small partners may refer to





This chapter and what we share is to use the signal R framework to create a simple group chat function, mainly to explain how to. NET MVC Use this framework, because this project has official documents (of course, all in English), there is no intention to write a share, the main purpose is to let friends in need to use web real-time communication, there is more a solution, after all, this is one of Microsoft's main push solution.



SIGNALR Online profile



The ASP. NET SignalR is a library for ASP. NET developers that simplifies the process of adding real-time WEB functionality to applications by developers. Real-time WEB functionality refers to the ability for server code to push content immediately when a connected client becomes available, rather than having the server wait for the client to request new data.



SIGNALR also offers a very simple and easy-to-use high-level API that allows the server side to invoke JavaScript functions on the client individually or in bulk, and makes it easy to manage connections, such as client connections to the server, or disconnection, client teaming, and client authorization. The use of SIGNALR is very easy to implement.



SIGNALR will communicate with the client in real-time to ASP. NET. Of course, this is useful, and there is enough extensibility. In the past, users need to refresh the page or use AJAX polling to achieve real-time display data, and now as long as the use of SIGNALR, it can be easily implemented. The most important thing is that you don't have to re-establish your project to use an existing ASP. NET project can be used seamlessly with SIGNALR.



Group Chat instance Effects



Let's take a look at the effect of the test case:






interface and its simple, style is not considered here, mainly to show its usage, here are the functions involved:



1. Statistics on number of people online



2. Display the nickname and connection method of the number of people online (this test case supports WebSockets and longpolling (long Connection))



3. Group chat Information



How to use SIGNALR in MVC



First, we usually practice creating MVC's Web project and then through the NuGet console command: Install-package Microsoft.AspNet.SignalR joins the SignalR dependency, the packages are automatically added as follows:


<package id="Microsoft.AspNet.SignalR" version="2.2.2" targetFramework="net45" />

<package id="Microsoft.AspNet.SignalR.Core" version="2.2.2" targetFramework="net45" />

<package id="Microsoft.AspNet.SignalR.JS" version="2.2.2" targetFramework="net45" />

<package id="Microsoft.AspNet.SignalR.SystemWeb" version="2.2.2" targetFramework="net45" />


and automatically add the relevant JS file to the script folder in the MVC project:



Jquery.signalr-2.2.2.min.js



Jquery.signalr-2.2.2.js



Then we need to create a class with a file name called Startup.cs in the project-level directory, where the main content is incomplete:


[assembly: OwinStartup(typeof(Stage.Api.Extend.Startup))]

namespace Stage.Api.Extend

{

  public class Startup

  {

    public void Configuration(IAppBuilder app)

    {

      app.MapSignalR("/chat", new Microsoft.AspNet.SignalR.HubConfiguration

      {

        EnableDetailedErrors = true,

        EnableJavaScriptProxies = true

      });

    }

  }

}


First, we analyze the points from the top down:



1. TheOwinStartup(Type)constructor passes a type, and this type corresponds to the startup class that we created, which marks the starting position by the constructor class;



2.namespace Stage.Api.Extendis the namespace of my project, this can be arbitrarily defined;



3. Thepublic void Configuration(IAppBuilder app)function is fixed must, where the program will first enter the method to execute the inside of the logic code;



4.app.MapSignalRis the extension of the Iappbuilder interface method, he has a variety of manifestations, here I choose, here ispublic static IAppBuilder MapSignalR(this IAppBuilder builder, string path, HubConfiguration configuration);a bit similar to the MVC route, here is the main note is this path parameter, in front of the page need to use this way;



To the background needs of the configuration is actually completed, the following is the specific business logic to operate the class, a new class (here I named Chathub) and inherit the hub (which is provided by the SIGNALR framework), and then the logic code is as follows:


Public class ChatHub : Hub

  {

    //

    Public int Num = 10001;

    Public static List<MoHubUser> _Users = new List<MoHubUser>();

 

    /// <summary>

    /// Add chat people

    /// </summary>

    /// <param name="user"></param>

    Public void AddUser(MoHubUser user)

    {

 

      user.Id = Context.ConnectionId;

      If (!_Users.Any(b => b.Id == user.Id))

      {

        _Users.Add(user);

      }

 

      //Clients.All.newUser(user);

      Clients.All.userList(_Users);

    }

 

    /// <summary>

    /// send Message

    /// </summary>

    /// <param name="user"></param>

    /// <param name="message"></param>

    Public void SendAll(MoHubUser user, string message)

    {

      Clients.All.addNewMessageToPage(user, message);

    }

 

    /// <summary>

    /// A chatter quits to notify all online people to reload the number of chats

    /// </summary>

    /// <param name="stopCalled"></param>

    /// <returns></returns>

    Public override System.Threading.Tasks.Task OnDisconnected(bool stopCalled)

    {

      Var user = _Users.SingleOrDefault(x => x.Id == Context.ConnectionId);

      If (user != null)

      {

        _Users.Remove(user);

        Clients.All.userList(_Users);

      }

      Return base.OnDisconnected(stopCalled);

    }

  }

The above 3 methods do: Add the chat to list, send information to the client, a connection fails to notify the effective chat reload information, it is worth paying attention to the re-public override System.Threading.Tasks.Task OnDisconnected(bool stopCalled)method to achieve capture and remove the failed connection (here is the message of the chat); The whole test case is context.connectionid to ensure the uniqueness of the connection, as long as there is a new link request, then the server will assign a unique string to the link, when the client closes the page or close the link this is the Ondisconnected method can be captured in the invalid link conne Ctionid, so that the removal of the failure of the chat person's requirements; for the convenience of the code, a chat person information class is created here:



publicclassMoHubUser

  {

 

    publicstringId {get;set; }

    publicstringNickName {get;set; }

    publicstringTransportMethod {get;set; }

  }

The chat room code in the background is so simple, so let's look at how to write the code, and here I'll give my HTML layout code:


@{   ViewBag.Title = "Shen Niu Chat Room - SignalR"; } <style type="text/css">   .p_left {     Width: 70%;     Float: left;   }     .p_right {     Width: 28%;     Float: left;   }     .ul {     List-style: none;     Border: 1px solid #ccc;     Height: 500px;     Overflow-y: scroll;     Color: black;   }       .ul li {       Padding-top: 5px;       Padding-right: 25px;     }     .ul_user {     List-style: none;   }       .ul_user li {       Padding-top: 5px;     }     .send {     Position: relative;     Background: #eae7e7;     Border-radius: 5px; /* Rounded corners */     Padding-top: 4px;     Padding-left: 5px;     Margin-top: 13px;   }       .send .arrow {       Position: absolute;       Top: -16px;       Font-size: 0;       Border: solid 8px;       Border-color: #fff #fff #eae7e7 #fff;     } </style> <h3>@ViewBag.Title Online number: <span id="sapnUserTotal">0</span> people</h3> <p class="container text-left">   <p class="p_left">     <ul class="ul" id="discussion"></ul>     <textarea rows="5" class="form-control" id="message" maxlength="500" placeholder="Start chatting. . ." style="max-width: 100%"></textarea><br />     <input type="button" id="sendmessage" value="send" class="btn btn-default" />     <input type="hidden" id="displayname" />   </p>   <p class="p_right">     <ul id="users" class="ul_user"></ul>   </p> </p>   <script src="~/Scripts/jquery.signalR-2.2.2.min.js"></script> @*<script src="~/chat/hubs"></script>*@

There are two options for the client to write here. One is to use the generated proxy directly, and the proxy that does not need to be automatically generated uses the method of manually creating the proxy. For the simplicity of the content, here is a simple explanation of the automatically generated proxy. And more is to share the way to manually create proxy links;

Use the generated proxy to get the link

First, we need to reference the path of the auto-generated proxy through the Script tag: <script src="~/chat/hubs"></script> , note that the path/chat here corresponds to the Startup.cs in front. The app.MapSignalR("/chat" path is configured in the file, and the /hubs fixed wording (at least I haven't tested it yet), only the ~/chat/hubs is applied first, so that the generated one can be used later. Agent, first paragraph code:


Var chat = $.connection.chatHub;     chat.client.newUser = function (user) {       $("#users").append(' <li><strong>' + user.NickName + '[' + user.TransportMethod + ']</strong></li>');     };       chat.client.userList = function (users) {       Console.log(users);       $("#sapnUserTotal").html(users.length);       $.each(users, function (i, item) {         $("#users").append(' <li>[' + item.TransportMethod + '] <strong>' + item.NickName + '</strong>(' + item.Id + ')</li> ');       });     };     chat.client.addNewMessageToPage = function (user, message) {       Console.log(user);       $("#discussion").append(' <li ><span><strong>' + user.NickName + '[' + user.TransportMethod + ']</strong>:</span><p class=" Send">' + message + '<p class="arrow"></p></p></li>');     };   //connection.hub.start({ transport: ['webSockets', 'longPolling'] }).done(function () {     // my.TransportMethod = connection.hub.transport.name;     // chat.server.addUser(my);       // $('#sendmessage').click(function () {     // //console.log(chat);     // var content = $.trim($('#message').val());     // if (content.length <= 0) { $('#message').val('').focus(); return; }     // chat.server.sendAll(my, content);     // $('#message').val('').focus();     // });     //}).fail(function () {     // alert ("Link chat room failed, please refresh the page.");     //});

Let's gradually analyze the code to note:


Var my = { NickName: "神牛001", TransportMethod: "" };

    Var connection = $.hubConnection("/chat/hubs");

    Var chat = connection.createHubProxy('chatHub');

 

    Chat.on("userList", function (users) {

      Console.log(users);

      $("#sapnUserTotal").html(users.length);

      $("#users").html("");

      $.each(users, function (i, item) {

        $("#users").append(' <li>[' + item.TransportMethod + '] <strong>' + item.NickName + '</strong>(' + item.Id + ')</li> ');

      });

    });

 

    Chat.on("addNewMessageToPage", function (user, message) {

      Console.log(user);

      $("#discussion").append(' <li ><span><strong>' + user.NickName + '[' + user.TransportMethod + ']</strong>:</span><p class=" Send">' + message + '<p class="arrow"></p></p></li>');

 

      Var p = document.getElementById('discussion');

      //p.scrollTop = p.scrollHeight;

      p.scrollTop = 999999;

    });

 

    Var nickName = prompt("Please enter a nickname:", my.NickName);

    my.NickName = nickName.length > 0 ? nickName : my.NickName;

    $('#displayname').val(nickName);

    $('#message').focus();

    

 

    Connection.start({ transport: ['webSockets', 'longPolling'] }).done(function () {

 

      my.TransportMethod = connection.transport.name;

      //console.log(my.TransportMethod);

      Chat.invoke("addUser", my);

 

      $('#sendmessage').click(function () {

        Var content = $.trim($('#message').val());

        If (content.length <= 0) { $('#message').val('').focus(); return; }

 

        Chat.invoke("sendAll", my, content);

        $('#message').val('').focus();

      });

    });


1. var chat = $.connection.chatHub; The chatHub here corresponds to the ChatHub class we created and inherits from Hub. Since the js variable starts with lowercase, this is chatHub. This sentence means that we link to us. Backend the ChatHub class, and then you can use the method inside (this is similar to the writing of some ajax request in the early webform)

2. Receive the notification of the server notification through chat.client.xxx, and the method name corresponding to this xxx and the Clients.All.xxx of our backend, the corresponding examples in this chapter are: chat.client.userList = function (users) {} corresponds to Clients.All.userList(_Users); so the backend can directly notify the client's corresponding method; note that my backend Clients.All is used to notify all clients, if you need to notify the specified link The ones used are: T Client(string connectionId);

3. chat.client is the backend call client, the opposite chat.server is the client request server, and the same as above, the request server method is specified by chat.server.xxx, pay attention to the server method at this time. Is a public method that inherits the subclass of the class Hub (this section corresponds to: chat.server.sendAll(my, content) corresponds to the public void SendAll(MoHubUser user, string message) function in the ChatHub.cs file)

4. connection.hub.start({ transport: ['webSockets', 'longPolling'] }) to specify the interactive protocol to run

The above is the way to use the generation proxy, writing according to the above points of attention should not be a problem;

Use a manual create reverse proxy to link

Instead of using the generated code, we only need to modify the front-end. The background code does not need to be changed or set without change. First, we remove the code that refers to the automatic proxy proxy mentioned above. Because this time is not needed, we still go first. Code:



Also note the following points:

1. var connection = $.hubConnection("/chat/hubs"); Create a link, where the path also corresponds to the backend app.MapSignalR("/chat" , the path is consistent

2. var chat = connection.createHubProxy('chatHub'); to create a reverse proxy link, where name:chatHub corresponds to the backend ChatHub class name

3. Use the on("xxx", function(){}) function to bind the event that the server notifies the client. xxx corresponds to xxx in Clients.All.xxx.

4. connection.start({ transport: ['webSockets', 'longPolling'] }) to set the allowed link method and start the link

5. connection.transport.name to get the name of the link. If the default start is not set, there are several types: webSockets, foreverFrame, serverSentEvents, longPolling

6. chat.invoke("xxx", param1, param2) maps the public methods of the class that inherits the class Hub by invoke, where the instance corresponds to: chat.invoke("sendAll", my, content) corresponds to public void SendAll( MoHubUser user, string message)

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.