Asp.net MVC signalr to do real-time web chat instance code

Time:2021-9-5

The content shared with you in this chapter is to use the signal R framework to create a simple group chat function. It mainly explains how to use this framework in MVC of. Net. Since the project has official documents (all in English of course), we don’t plan to write a sharing article later. The main purpose is to let friends have more solutions when they need to use web real-time communication, After all, this is one of the solutions mainly promoted by Microsoft.

Signalr online profile

Asp.net signalr is a library for asp.net developers, which can simplify the process of developers adding real-time web functions to applications. The real-time web function refers to the function that when the connected client becomes available, the server code can immediately push content to it, rather than making the server wait for the client to request new data.

Of course, signalr also provides a very simple and easy-to-use high-level API, so that the server can call JavaScript functions on the client individually or in batches, and it is very convenient for connection management. For example, it is very easy to use signalr to connect or disconnect the client to the server, group the client, and authorize the client.

Signalr brings real-time communication with clients to ASP. Net. Of course, this is not only easy to use, but also has enough scalability. In the past, users needed to refresh the page or use ajax polling to display data in real time. Now they can simply use signalr. Most importantly, you can use signalr seamlessly using an existing ASP. Net project without having to re-establish the project.

Group chat instance effect

Let’s take a look at the effect of the test case first. The effect diagram:

The interface is very simple. The style is not considered here. It is mainly to show its usage. The functions involved here include:

1. Count the number of online people

2. Display the nickname and connection mode of online people (this test case supports WebSockets and longpolling)

3. Group chat information

How to use signalr in MVC

First, we create the MVC web project as usual, and then add the dependency of signalr through the nuget console command: install package microsoft.aspnet.signalr. The automatically added packages are as follows:


 <package version="2.2.2" targetFramework="net45" />
 <package version="2.2.2" targetFramework="net45" />
 <package version="2.2.2" targetFramework="net45" />
 <package version="2.2.2" targetFramework="net45" />

And automatically add relevant JS files 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 the file name startup.cs in the project level directory. The main contents can not be completed:


[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, let’s analyze the points of attention from top to bottom:

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

2.  namespace Stage.Api.Extend Is the namespace of my project, which can be defined freely;

3.  public void Configuration(IAppBuilder app) The function is fixed and necessary. Here, the program will first enter this method to execute the logic code inside;

4.  app.MapSignalR It is an extended iappbuilder interface method. It has many forms. Here I choosepublic static IAppBuilder MapSignalR(this IAppBuilder builder, string path, HubConfiguration configuration); , it looks a little similar to our MVC routing. Here, we mainly pay attention to the path parameter, which needs to be used in the front-end page;

Here, the configuration required in the background has been completed. The following is the business logic processing class to be operated. Create a new class (here I call it chathub) and inherit the hub (provided by signalr framework). 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 person
    /// </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>
    ///When a chat person exits, all online people are notified 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 three methods are done respectively: add chat people to the list, send information to the client, and notify each effective chat person to reload the information after a connection fails; What is noteworthy here is through republic override System.Threading.Tasks.Task OnDisconnected(bool stopCalled) Method to capture and remove the invalid connection (here is the chat person’s information); The whole test case uses context.connectionid to ensure the uniqueness of the connection. As long as there is a new link request, the server will assign a unique string to the link. When the client closes the page or closes the link, it can capture the connectionid of the invalid link in the ondisconnected method, which meets the requirement of removing the invalid chat person; For the convenience of the code, a chat person information class is created here:


public class MoHubUser
  {

    public string Id { get; set; }
    public string NickName { get; set; }
    public string TransportMethod { get; set; }
  }

Here, the background chat room code is completed, which is so simple; Let’s look at how to write code in the attempt. Here I give my HTML layout code first:

@{
  Viewbag.title = "Shenniu chat room - signalr";
}
<style type="text/css">
  .div_left {
    width: 70%;
    float: left;
  }

  .div_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; /*  Fillet*/
    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 number of people online: < span > 0 < / span ></h3>
<div>
  <div>
    <ul></ul>
    < textarea rows = "5" MaxLength = "500" placeholder = "start chatting..." style = "max width: 100%" > < / textarea > < br / >
    < input type = "button" value = "send" / >
    <input type="hidden" />
  </div>
  <div>
    <ul></ul>
  </div>
</div>

<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 directly use the generated agent for operation, and the other is to manually create the agent without automatic generation; For the sake of brevity of the content, we only briefly explain the method of automatically generating proxy, and more importantly, we share the method of manually creating proxy links;

Get links using the generated proxy

First, we need to refer to the path of the auto generated agent through the script tag:<script src="~/chat/hubs"></script> Note that the path / chat here corresponds to what we configured in the previous startup.cs file app.MapSignalR("/chat" Path, and the following / hub is fixed (at least I haven’t tried more at present). Only after applying this ~ / chat / hub, can the generated agent be used later. First, the above 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><div>' + message + '<div></div></div></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 ("failed to link the chat room, please refresh the page.");
    //});

Let’s analyze the code step by step. Note:

1.  var chat = $.connection.chatHub; The chathub here corresponds to the chathub class we created and inherited from the hub. Since the JS variable starts in lowercase, this is chathub. This sentence means that we have linked to our backend chathub class, and then we can use the methods inside (this is a bit similar to the writing method of some Ajax requests in early webform)

2. Receive the message notified by the server through chat.client.xxx, and the method name corresponding to this XXX corresponds to our backend clients.all.xxx. The examples in this chapter correspond to: chat.client.userlist = function (users) {} corresponds to clients.all.userlist (_ Users); In this way, the back end can directly notify the corresponding method of the client; Note that my backend clients.all here means to notify all clients. If you need to notify the specified link, you need to use: T Client(string connectionId);method

3. Chat.client is the back-end calling client, and the opposite chat.server is the client requesting server. As above, specify the requested server method through chat.server.xxx. Note that at this time, the server method refers to the public method inheriting the subclass of the class hub (this article corresponds to the public method in the chathub.cs file corresponding to chat.server.sendall (my, content)) public void SendAll(MoHubUser user, string message) Function)

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

The above is how to use the generation agent. It should not be a problem to write according to the above precautions;

Use manually created reverse proxy to link

Instead of using the generated code, we only need to modify the front end, and the background code or settings do not need to be changed; First, let’s remove the code that the script refers to the automatic agent, because it’s not needed at this time. Let’s start with the code:

Var my = {nickname: "Shenniu 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><div>' + message + '<div></div></div></li>');

      var div = document.getElementById('discussion');
      //div.scrollTop = div.scrollHeight;
      div.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();
      });
    });

The following precautions are also listed:

1.  var connection = $.hubConnection("/chat/hubs"); Create a link. The path here also corresponds to the app. Mapsignalr (“/ chat”) on the back end, and the path is consistent

2.  var chat = connection.createHubProxy('chatHub'); To create a reverse proxy link. The name: chathub here corresponds to the chathub class name of the back end

3. Bind the events notified by the server to the client through the on (“XXX”, function() {}) function. XXX corresponds to XXX in clients.all.xxx

4.  connection.start({ transport: ['webSockets', 'longPolling'] }) To set the allowed link mode 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) uses invoke to map the public methods of classes that inherit the class hub. Here, the instance corresponds to: chat.invoke("sendAll", my, content) correspondingpublic void SendAll(MoHubUser user, string message)

Write at the end

Here, if the above points of attention are met, the basic signalr link can be used successfully. There are many points of attention, but they are all summarized experience. I hope it will be helpful to everyone’s learning, and I hope you can support developpaer more.

Recommended Today

Beautify your code VB (VBS) code formatting implementation code

However, vb.net does have many new functions that VB6 does not have. The automatic typesetting of code is one, which is the function we want to realize today – VB code formatting.Let’s look at the effect: Before formatting: Copy codeThe code is as follows: For i = 0 To WebBrowser1.Document.All.length – 1 If WebBrowser1.Document.All(i).tagName = […]