Как создать индикатор ввода для программы чата в ASP.NET

1656593423 kak sozdat indikator vvoda dlya programmy chata v aspnet

автор Нео Игадаро

rL8C1RFC-jcvKMHqgTADa-eFdtkMrl3JjLh0
Фото: freestocks.org на Unsplash

Для выполнения этого руководства необходимо базовое понимание ASP.NET и jQuery.

Когда вы используете программу для чата, знать, когда человек, с которым вы общаетесь, набирает сообщение, может улучшить ваш опыт работы. Это дает вам определенную обратную связь, что вы не одиноки в разговоре и что вам поступает сообщение.

В этом учебнике мы рассмотрим несколько простых шагов по созданию этой функции с помощью C#, .NET и Pusher.

В конце этого урока мы будем иметь что-то вроде этого:

rwOg-HkLtiydf-37RuU7DvGykJJyt8fz-P4P

Этот учебник предусматривает предварительные знания о:

  • C#
  • .NET MVC
  • JavaScript (jQuery)

Когда вы будете готовы, начнём.

Настройка нашего проекта

Мы будем использовать Visual Studio, которая является IDE, которая широко используется для создания проектов .NET. Visual Studio 2017 является бесплатным и доступным для большинства операционных систем. Вы можете просмотреть детали установки здесь.

После установки Visual Studio запустите ее и создайте новый проект, нажав Новый проект из приборной панели. Следуя за Новый проект волшебник мы:

  • Установите C# как наш язык
  • Выберите проект .NET MVC в качестве шаблона
  • Введите название проекта (например, HeyChat — но подойдет любое название)
  • Заполните название решения (т.е. название программы – «HeyChat» или любое название).
wHa3qOf05-fbAXL-Ea06A5GNCKi3nJeGoiYq

Создание кода на стороне сервера (C#).

Чтобы отображать индикатор ввода, наше приложение для чата должно иметь возможность распознавать, кто печатает в любой момент времени. Для этого мы прибавим некоторую ограниченную форму идентификации. Мы вообще не производим никакой аутентификации, потому что это руководство не требует ее.

? Для целей этого учебника мы будем считать, что чат открыт для всех пользователей. Все, что нужно, это то, чтобы наши пользователи указали свои имена при первом входе.

Определение маршрута

Мы можем определить некоторые из маршрутов, которые нам нужны для создания этой функции, а именно:

  • Домашний маршрут, отображающий первую страницу, берущую имя пользователя.
  • Маршрут входа, который принимает POST запрос имени пользователя.
  • Маршрут чата, отображающий просмотр чата.

? Возможно, нам понадобятся другие маршруты, но этого достаточно для начала.

Чтобы добавить эти маршруты, мы открываем файл RouteConfig.cs файл в App_Start каталог нашей программы. И в него мы добавляем определённые нами маршруты.

routes.MapRoute(        name: "Home",        url: "",        defaults: new { controller = "Home", action = "Index" }    );
    routes.MapRoute(        name: "Login",        url: "login",        defaults: new { controller = "Login", action = "Index" }    );
    routes.MapRoute(        name: "ChatRoom",        url: "chat",        defaults: new {controller = "Chat", action="Index"}    );

Использование Домой маршрут как образец, в определении маршрута указано, что / запросы будут обрабатываться HomeController который находится в Controllers/HomeController.cs файл и Index способ этого контроллера. Далее мы создадим контролеры, которые нам понадобятся.

Создание контроллеров и методов действий

Чтобы создать новый контроллер, щелкните правой кнопкой мыши Контроллер каталог и выберите Add → Controller. В полученной форме вводим имя нашего контроллера и выбираем пустой шаблон.

? Когда наша программа создается, она включает в себя HomeController с методом действия Index по умолчанию, поэтому мы выполним приведенные выше шаги для создания наших LoginController и ChatController.

В нашем классе LoginController мы создаем метод действия Index, указывающий [HttpPost] в верхней части метода действия, чтобы указать, что он обрабатывает POST запросы.

public class LoginController : Controller    {        [HttpPost]        public ActionResult Index()        {
        }    }

Действие Index в LoginController получит полезную нагрузку запроса, прочтет имя пользователя из полезной нагрузки и назначит его текущему сеансу пользователя. Затем он перенаправит нашего пользователя на страницу чата. Когда мы добавим это к нашему методу действия, мы получим:

public class LoginController : Controller    {        [HttpPost]        public ActionResult Index()        {            string user = Request.Form["username"];            if (user.Trim() == "") {                return Redirect("/");            }            Session["user"] = user;            return Redirect("/chat");        }    }

? В реальном приложении для чата мы добавляем пользователя в базу данных и обозначаем пользователя как вошедшего, чтобы другие пользователи могли видеть доступные параметры чата. Но это выходит за рамки этого учебника, поэтому достаточно добавить к сеансу.

В наш класс ChatController мы добавим метод действия Index. Действие Index в ChatController отобразит наше представление чата и передаст текущему пользователю представление.

public class ChatController : Controller    {        public ActionResult Index()        {            if (Session["user"] == null) {                return Redirect("/");            }
            ViewBag.currentUser = Session["user"];
            return View ();        }    }

? По умолчанию методы действия обрабатывают GET запросы, поэтому нам не нужно будет добавлять[[HttpGet] к вершине нашего метода. Мы также добавили простую проверку, чтобы предотвратить доступ к странице чата, если не вошел пользователь.

Не забывайте о нашем Домашнем маршруте. В HomeController мы добавим код воспроизведения главной страницы.

public class HomeController : Controller    {        public ActionResult Index()        {            if ( Session["user"] != null ) {                return Redirect("/chat");            }
            return View();        }    }

? Мы также добавили небольшую проверку, чтобы предотвратить многократный вход в один сеанс пользователя.

На данный момент мы создали контроллеры и методы обслуживания наших представлений (которые мы еще не создали), поэтому попытка запустить это приведет к некоторым ошибкам! Давайте поправим это.

Реализация взглядов программы

Исходя из маршрутов, которые мы уже определили, нам понадобятся два представления:

  • Вид первой страницы с формой входа – предоставляется Indexметод действия HomeController класс
  • Подача чата, где будет видна функция индикатора ввода — обслуживается ChatController класс Index метод действия

Главная страница/страница входа

Для нашей главной страницы мы создадим страницу с формой, которая запрашивает имя пользователя и показывает им кнопку входа. Ссылаясь на код нашего контроллера:

public class HomeController : Controller    {        public ActionResult Index()        {            if ( Session["user"] != null ) {                return Redirect("/chat");            }            return View();        }    }

? Вiew функция создает ответный просмотр, который мы возвращаем. Когда Вiew() вызывается, C# ищет представление по умолчанию для вызывающего класса контроллера. Этим видом по умолчанию является index.cshtml файл, найденный в Views каталога в каталоге с таким же названием, что и контроллер. То есть представление по умолчанию для класса HomeController будет Views/Home/index.cshtml файл.

Чтобы создать нашу HomeController просмотр по умолчанию, мы:

  • Щелкните правой кнопкой мыши каталог Views и выберите Add New Folder,
  • Заполнить Домой как имя папки,
  • Щелкните правой кнопкой мыши на только что созданном Домой папку и выберите Add New View,
  • Заполните название представления (в нашем случае индекс), выберите Razor в режиме просмотра и нажмите OK.

Теперь, когда мы создали файл просмотра первой страницы, мы добавим разметку для формы входа.

<div class="container">      <div class="row">        <div class="col-md-5 col-md-offset-4">          <div class="panel panel-default">            <div class="panel-body">              <form action="/login" method="post" style="margin:0">                <div class="form-group">                  <input type="text" name="username" id="username"                       placeholder="Enter Username" class="form-control"                       required minlength="3" maxlength="15" />                </div>                <button type="submit" class="btn btn-primary btn-block">                  Enter Chat                </button>              </form>            </div>          </div>        </div>      </div>    </div>

Страница чата

Мы создадим представление для страницы чата, выполнив те же действия, что и выше, но используя Chat как название нашей папки, а не Home.

В режиме просмотра чата мы добавляем разметку, чтобы получить боковую панель доступных пользователей и область для общения.

<!DOCTYPE html>    <html>    <head>      <title>pChat — Private Chatroom</title>      <link rel="stylesheet" href="    </head>    <body>            @{                var currentUser = ViewBag.currentUser;            }        <!-- Navigation Bar -->        <nav class="navbar navbar-inverse">          <div class="container-fluid">            <div class="navbar-header">              <a class="navbar-brand" href="#">pChat</a>            </div>            <ul class="nav navbar-nav navbar-right">              <li><a href="#">Log Out</a></li>            </ul>          </div>        </nav>        <!-- / Navigation Bar -->        <div class="container">          <div class="row">            <div class="col-xs-12 col-md-3">              <aside class="main">                <div class="row">                  <div class="col-xs-12">                    <div class="panel panel-default users__bar">                      <div class="panel-heading users__heading">                        Online Users (1)                      </div>                      <div class="panel-body users__body">                        <ul class="list-group">                        @if( @currentUser == "Daenerys" ) {                            <li class="user__item">                                <div class="avatar"></div> <a href="#">Jon</a>                            </li>                        } else if( @currentUser == "Jon") {                            <li class="user__item">                                <div class="avatar"></div> <a href="#">Daenerys</a>                            </li>                        }                        </ul>                      </div>                    </div>                  </div>                </div>              </aside>            </div>            <div class="col-xs-12 col-md-9 chat__body">              <div class="row">                <div class="col-xs-12">                  <ul class="list-group chat__main">                    <div class="row __chat__par__">                      <div class="__chat__ from__chat">                        <p>Did you see Avery's sword???</p>                      </div>                    </div>                    <div class="row __chat__par__">                      <div class="__chat__ receive__chat">                        <p>Err Looked normal to me...</p>                      </div>                    </div>                    <div class="row __chat__par__">                      <div class="__chat__ receive__chat">                        <p>maybe I'm a hater</p>                      </div>                    </div>                    <div class="row __chat__par__">                      <div class="__chat__ from__chat">                        <p>Lmaooo</p>                      </div>                    </div>                  </ul>                </div>                <div class="chat__type__body">                  <div class="chat__type">                    <textarea id="msg_box" placeholder="Type your message"></textarea>                  </div>                </div>                <div class="chat__typing">                  <span id="typerDisplay"></span>                </div>              </div>            </div>          </div>        </div>        <script src="        </body>    </html>

Мы используем механизм шаблонов razor, который дает нам возможность читать данные, передаваемые из кода C#, и назначать их переменным, которые можно использовать в нашем интерфейсе. Использование @{ var currentUser = ViewBag.currentUser } мы передали имя текущего пользователя, что скоро пригодится.

? Чтобы все было быстро и просто, мы предположили, что есть только два возможных пользователя: Daenerys или Джна. Итак, используя бритву @if{ } условии, мы показываем, с кем можно общаться.

Теперь, когда у нас есть свои взгляды, мы можем перейти к нашей функции индикатора ввода!

Реализация индикатора набора текста

Прослушивание события набора текста

В большинстве программ чата эта функция становится видимой, когда кто-то вводит. Чтобы реализовать это, мы начнем с прослушивания события ввода текста в текстовой области чата с помощью jQuery. Мы также пройдем currentUser переменную, которую мы определили раньше с помощью britty для нашего сценария.

var currentUser = @currentUser;
    $('#msg_box').on('keydown', function () {      //stub    });

Мы добавили слушателя к keydown событие в нашей области ввода, чтобы помочь нам отслеживать, когда кто-то печатает.

Теперь, когда мы создали наших слушателей, мы заставим их отправлять печатающее сообщение другим участникам чата. Для этого мы создадим конечную точку в нашем коде C#, чтобы получить этот запрос и передать его через Pusher.

Мы реализуем весь клиентский код (предполагая, что наша конечная точка C# существует, тогда мы фактически создадим конечную точку позже).

? Чтобы предотвратить чрезмерные запросы к нашему коду C#, то есть отправку запроса, когда каждая клавиша на клавиатуре нажимается или отпускается, мы будем регулировать отправку запросов с помощью функции устранения отказов. Эта функция отказов просто игнорирует функцию на время, если она продолжает возникать.

// Debounce function    // Credit: 
    // Returns a function, that, as long as it continues to be invoked, will not    // be triggered. The function will be called after it stops being called for    // N milliseconds. If `immediate` is passed, trigger the function on the    // leading edge, instead of the trailing.    function debounce(func, wait, immediate) {        var timeout;        return function() {            var context = this, args = arguments;            var later = function() {                timeout = null;                if (!immediate) func.apply(context, args);            };            var callNow = immediate && !timeout;            clearTimeout(timeout);            timeout = setTimeout(later, wait);            if (callNow) func.apply(context, args);        };    };

Теперь, когда у нас есть a debounce функцию, мы создадим функцию обратного вызова для нашего keydown событие:

var isTypingCallback = debounce( function() {        $.post('/chat/typing', {            typer: currentUser,        });    }, 600, true);

и передать обратный вызов нашим слушателям событий.

$('#msg_box').on('keydown',isTypingCallback);

Создание конечной точки, вызванной событием ввода

Раньше наши слушатели событий присылали a POST запрос к /chat/typing Маршрут на стороне клиента. Теперь мы создадим этот маршрут, который будет передавать событие ввода другим клиентам с помощью Pusher.

Сначала мы создадим маршрут для конечной точки в нашем RouteConfig.cs файл.

...    routes.MapRoute(        name: "UserTyping",        url: "chat/typing",        defaults: new { controller = "Chat", action = "Typing" }    );

? Мы создали эту конечную точку для обработки Typing метод действия ChatController.

Далее мы создадим наш метод действия Typing в файле ChatController:

[HttpPost]    public ActionResult Typing()    {        //stub    }

Использование Pusher для обновления нашей программы в режиме реального времени

Наши /`чат/typing` конечная точка получит сообщение о пользователе, который вводит текст. Мы собираемся использовать Pusher, чтобы передать это всем остальным.

На нашей информационной панели Pusher мы создадим новую программу, которая заполнит запрашиваемую информацию – название программы, технологию интерфейса и т.д. Вы можете зарегистрироваться бесплатно, если у вас нет аккаунта. Далее мы установим Сервер Pusher пакет в нашем коде C# с помощью NuGet, менеджера упаковщиков для .NET.

iXWg6pncTloovKOm5rJjn3GhagikRa4BeRfs

? Чтобы установить пакет, щелкните правой кнопкой мыши Packages каталога, выберите aОпция пакета dd, и выберите PСервер usher пакет.

Затем мы добавим трансляцию Pusher к нашему. Ввод текста событие действия. Чтобы использовать Pusher, нам придется импортировать файл Сервер Pusher пространство имен в наш код.

...    using PusherServer;
    namespace HeyChat.Controllers    {        public class ChatController : Controller        {          ...
          [HttpPost]          public ActionResult Typing()          {              string typer        = Request.Form["typer"];              string socket_id    = Request.Form["socket_id"];
              var options = new PusherOptions();              options.Cluster = "PUSHER_APP_CLUSTER";
              var pusher = new Pusher(              "PUSHER_APP_ID",              "PUSHER_APP_KEY",              "PUSHER_APP_SECRET", options);
              pusher.TriggerAsync(              "chat",              "typing",              new { typer = typer },              new TriggerOptions() { SocketId = socket_id });
              return new HttpStatusCodeResult(200);          }         ...

Мы инициализировали Pusher с помощью нашего PUSHER_APP_ID, PUSHER_APP_KEY, PUSHER_APP_SECRETи PUSHER_APP_CLUSTER (обязательно замените их фактическими значениями из информационной панели). Затем мы транслируем объект, содержащий машинка — какой человек вводит — на typing событие через chat канал.

? Мы добавили нew TriggerOptions() { SocketId = socket_id } к нашему Pusher triggerAsync функция. Это делается для того, чтобы отправитель трансляции также не получал трансляцию. Для этого мы предположили, что получаем socket_id в нашей полезной нагрузке вместе с typer, поэтому на стороне нашего клиента мы добавим его к посланной полезной нагрузке.

Теперь, когда происходит ввод текста, наш код C# транслирует его на Pusher. Осталось только прослушать эту трансляцию и отобразить функцию «xxxx набирает…».

Сначала мы инициализируем Pusher в разделе сценариев нашей страницы чата, используя наш PUSHER_APP_KEY и PUSHER_APP_CLUSTER (еще раз замените их значениями из своей информационной панели).

var pusher = new Pusher('PUSHER_APP_KEY', {        cluster:'PUSHER_APP_CLUSTER'    });

Чтобы применить освобождение от вещателя, которое мы упоминали ранее, мы получим идентификатор сокета от нашего клиента pusher экземпляр и измените нашу полезную нагрузку для запроса на ввод к серверу, чтобы включить его.

var socketId = null;    pusher.connection.bind('connected', function() {      socketId = pusher.connection.socket_id;    });
    var isTypingCallback = debounce( function() {        $.post('/chat/typing', {            typer: currentUser,            socket_id: socketId // pass socket_id parameter to be used by server        });    }, 600, true);

Теперь, когда Pusher инициализирован на стороне нашего клиента, мы подпишемся на канал чата и внедрим нашу функцию с помощью typer прошел.

var channel = pusher.subscribe('chat');
    channel.bind('typing', function(data) {        $('#typerDisplay').text( data.typer + ' is typing...');
        $('.chat__typing').fadeIn(100, function() {            $('.chat__type__body').addClass('typing_display__open');        }).delay(1000).fadeOut(300, function(){            $('.chat__type__body').removeClass('typing_display__open');        });    });

Вывод

В этом учебнике мы рассмотрели использование популярной функции индикатора ввода с помощью Pusher, .NET, кода C# и некоторых jQuery. Мы также видели, как транслировать сообщение и избежать ответа отправителя на сообщение, которое он послал.

Эта публикация была впервые опубликована в Pusher.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *