WebSockets in action

Let's optimize the client-side implementation of the Tic-Tac-Toe application by using WebSockets for real-time communication:

  1. Go to the Tic-Tac-Toe Startup class in the Configure method and add the WebSockets middleware just before the communication middleware and the MVC middleware (remember that the middleware invocation order is important for assuring correct behavior):
        app.UseWebSockets(); 
        app.UseCommunicationMiddleware(); 
        ... 
  1. Update the communication middleware and add two new methods, with the first one being SendStringAsyncas follows: 
   private static Task SendStringAsync(WebSocket socket,
string data, CancellationToken ct =
default(CancellationToken)) { var buffer = Encoding.UTF8.GetBytes(data); var segment = new ArraySegment<byte>(buffer); return socket.SendAsync(segment, WebSocketMessageType.Text,
true, ct); }

The second one is ReceiveStringAsync and is used for WebSockets communication:

private static async Task<string> ReceiveStringAsync(
WebSocket socket, CancellationToken ct =
default(CancellationToken)) { var buffer = new ArraySegment<byte>(new byte[8192]); using (var ms = new MemoryStream()) { WebSocketReceiveResult result; do { ct.ThrowIfCancellationRequested(); result = await socket.ReceiveAsync(buffer, ct); ms.Write(buffer.Array, buffer.Offset, result.Count); }
while (!result.EndOfMessage); ms.Seek(0, SeekOrigin.Begin); if (result.MessageType != WebSocketMessageType.Text) throw new Exception("Unexpected message"); using (var reader = new StreamReader(ms, Encoding.UTF8)) { return await reader.ReadToEndAsync(); } } }
  1. Update the communication middleware and add a new method called ProcessEmailConfirmation for email confirmation processing via WebSockets:
public async Task ProcessEmailConfirmation(HttpContext context, WebSocket currentSocket, CancellationToken ct, string email)

{ UserModel user = await _userService.GetUserByEmail(email); while (!ct.IsCancellationRequested &&
!currentSocket.CloseStatus.HasValue &&
user?.IsEmailConfirmed == false) { if (user.IsEmailConfirmed) await SendStringAsync(currentSocket, "OK", ct); else { user.IsEmailConfirmed = true; user.EmailConfirmationDate = DateTime.Now; await _userService.UpdateUser(user); await SendStringAsync(currentSocket, "OK", ct); } Task.Delay(500).Wait(); user = await _userService.GetUserByEmail(email); } }
  1. Update the Invoke method in the communication middleware and add calls to the WebSockets-specific methods from the previous step, while still keeping the standard implementations for browsers that do not support WebSockets:
public async Task Invoke(HttpContext context) { 
  if (context.WebSockets.IsWebSocketRequest) 
    { 
      var webSocket = await context.WebSockets.
AcceptWebSocketAsync(); var ct = context.RequestAborted; var json = await ReceiveStringAsync(webSocket, ct); var command = JsonConvert.DeserializeObject<dynamic>(json); switch (command.Operation.ToString()) { case "CheckEmailConfirmationStatus": {await ProcessEmailConfirmation(context, webSocket,
ct, command.Parameters.ToString()); break; } } } else if (context.Request.Path.Equals("/CheckEmailConfirmationStatus")) //... keep the rest of the method as it was }
  1. Modify the scripts1.js file and add some WebSockets-specific code for opening and working with sockets:
        var interval; 
        function EmailConfirmation(email) { 
          if (window.WebSocket) { 
            alert("Websockets are enabled"); 
            openSocket(email, "Email"); 
          } 
          else { 
            alert("Websockets are not enabled"); 
            interval = setInterval(() => { 
              CheckEmailConfirmationStatus(email); 
            }, 5000); 
          } 
        } 

  1. Modify the scripts2.js file but keep the CheckEmailConfirmationStatus function the same. Add some WebSockets-specific code for opening and working with sockets and also redirecting the user to the game invitation page if their email has been confirmed:
     
 var openSocket = function (parameter, strAction) { 
   if (interval !== null) clearInterval(interval); 
 
   var protocol = location.protocol === "https:" ?  "wss:" : "ws:"; 
   var operation = "";    var wsUri = ""; 
 
   if (strAction == "Email") { 
      wsUri = protocol + "//" + window.location.host
+ "/CheckEmailConfirmationStatus"; operation = "CheckEmailConfirmationStatus"; } var socket = new WebSocket(wsUri); socket.onmessage = function (response) {
console.log(response); if (strAction == "Email" && response.data == "OK") { window.location.href = "/GameInvitation?email=" +
parameter; } }; socket.onopen = function () { var json = JSON.stringify({ "Operation": operation,
"Parameters": parameter }); socket.send(json); }; socket.onclose = function (event) { };
};

  1. When you start the application and proceed with the user registration, you will get the necessary information if WebSockets are supported. If they are, you will be redirected to the game invitation page like before, but with the benefit of a much faster processing time:

This concludes our look at client-side development and optimization under ASP.NET Core 3 for the moment. Now, you are going to learn how to further extend and finalize the Tic-Tac-Toe application with additional ASP.NET Core concepts that will help you in your daily work while building multi-lingual, production-ready web applications.

As a web application gets busier, we might want to minimize unnecessary round trips that are requesting data that can be kept for a period of time for retrieval and usage. Let's look at how to do this by introducing session and user cache management.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.218.167.41