Sample Code of ASP. NET MVC4 asynchronous chat room and mvc4 sample code
This article introduces the sample code of ASP. NET MVC4 asynchronous chat room and shares it with you, as follows:
Class diagram:
Domain Layer
IChatRoom. cs
using System;using System.Collections.Generic;namespace MvcAsyncChat.Domain{ public interface IChatRoom { void AddMessage(string message); void AddParticipant(string name); void GetMessages( DateTime since, Action<IEnumerable<string>, DateTime> callback); void RemoveParticipant(string name); }}
IMessageRepo. cs
using System;using System.Collections.Generic;namespace MvcAsyncChat.Domain{ public interface IMessageRepo { DateTime Add(string message); IEnumerable<string> GetSince(DateTime since); }}
ICallbackQueue. cs
using System;using System.Collections.Generic;namespace MvcAsyncChat.Domain{ public interface ICallbackQueue { void Enqueue(Action<IEnumerable<string>, DateTime> callback); IEnumerable<Action<IEnumerable<string>, DateTime>> DequeueAll(); IEnumerable<Action<IEnumerable<string>, DateTime>> DequeueExpired(DateTime expiry); }}
ChatRoom. cs
Using System; using System. collections. generic; using System. linq; using System. threading; using MvcAsyncChat. svcs; namespace MvcAsyncChat. domain {public class ChatRoom: IChatRoom {readonly ICallbackQueue callbackQueue; readonly implements dateTimeSvc; readonly implements messageRepo; public ChatRoom (ICallbackQueue callbackQueue, implements dateTimeSvc, implements messageRepo) {this. callbackQueue = callbackQueue; this. dateTimeSvc = dateTimeSvc; this. messageRepo = messageRepo;} public void AddMessage (string message) {var timestamp = messageRepo. add (message); foreach (var callback in callbackQueue. dequeueAll () callback (new [] {message}, timestamp);} public void AddParticipant ipant (string name) {AddMessage (string. format ("{0} has entered the room. ", name);} public void GetMessages (DateTime since, Action <IEnumerable <string>, DateTime> callback) {var messages = messageRepo. getSince (since); if (messages. count ()> 0) callback (messages, since); else callbackQueue. enqueue (callback);} public void RemoveParticipant (string name) {AddMessage (string. format ("{0} left the room. ", name ));}}}
InMemMessageRepo. cs
using System;using System.Collections.Generic;using System.Linq;namespace MvcAsyncChat.Domain{ public class InMemMessageRepo : IMessageRepo { public InMemMessageRepo() { Messages = new List<Tuple<string, DateTime>>(); } public IList<Tuple<string, DateTime>> Messages { get; private set; } public DateTime Add(string message) { var timestamp = DateTime.UtcNow; Messages.Add(new Tuple<string, DateTime>(message, timestamp)); return timestamp; } public IEnumerable<string> GetSince(DateTime since) { return Messages .Where(x => x.Item2 > since) .Select(x => x.Item1); } }}
CallbackQueue. cs
using System;using System.Collections.Generic;using System.Linq;namespace MvcAsyncChat.Domain{ public class CallbackQueue : ICallbackQueue { public CallbackQueue() { Callbacks = new Queue<Tuple<Action<IEnumerable<string>, DateTime>, DateTime>>(); } public Queue<Tuple<Action<IEnumerable<string>, DateTime>, DateTime>> Callbacks { get; private set; } public void Enqueue(Action<IEnumerable<string>, DateTime> callback) { Callbacks.Enqueue(new Tuple<Action<IEnumerable<string>, DateTime>, DateTime>(callback, DateTime.UtcNow)); } public IEnumerable<Action<IEnumerable<string>, DateTime>> DequeueAll() { while (Callbacks.Count > 0) yield return Callbacks.Dequeue().Item1; } public IEnumerable<Action<IEnumerable<string>, DateTime>> DequeueExpired(DateTime expiry) { if (Callbacks.Count == 0) yield break; var oldest = Callbacks.Peek(); while (Callbacks.Count > 0 && oldest.Item2 <= expiry) { yield return Callbacks.Dequeue().Item1; if (Callbacks.Count > 0) oldest = Callbacks.Peek(); } } }}
RequestModels folder entity class
EnterRequest. cs
Using System; using System. componentModel; using System. componentModel. dataAnnotations; namespace MvcAsyncChat. requestModels {public class EnterRequest {[DisplayName ("name")] [Required, StringLength (16), RegularExpression (@ "^ [A-Za-z0-9 _ \-] + $ ", errorMessage = "A name must be alpha-numeric. ")] public string Name {get; set ;}}}
GetMessagesRequest. cs
using System;namespace MvcAsyncChat.RequestModels{ public class GetMessagesRequest { public string since { get; set; } }}
SayRequest. cs
using System;using System.ComponentModel;using System.ComponentModel.DataAnnotations;namespace MvcAsyncChat.RequestModels{ public class SayRequest { [Required, StringLength(1024), DataType(DataType.MultilineText)] public string Text { get; set; } }}
ResponseModels folder entity class
GetMessagesResponse. cs
using System;using System.Collections.Generic;namespace MvcAsyncChat.ResponseModels{ public class GetMessagesResponse { public string error { get; set; } public IEnumerable<string> messages { get; set; } public string since { get; set; } }}
SayResponse. cs
using System;namespace MvcAsyncChat.ResponseModels{ public class SayResponse { public string error { get; set; } }}
ChatController. cs
Using System; using System. collections. generic; using System. linq; using System. web; using System. web. mvc; using System. web. mvc. async; using MvcAsyncChat. domain; using MvcAsyncChat. requestModels; using MvcAsyncChat. responseModels; using MvcAsyncChat. svcs; namespace MvcAsyncChat. controllers {public class ChatController: AsyncController {readonly IAuthSvc authSvc; readonly IChatRoom chatRoom; readonly IDateT ImeSvc dateTimeSvc; public ChatController (IAuthSvc authSvc, IChatRoom chatRoom, IDateTimeSvc dateTimeSvc) {this. authSvc = authSvc; this. chatRoom = chatRoom; this. dateTimeSvc = dateTimeSvc;} [ActionName ("enter"), HttpGet] public ActionResult ShowEnterForm () {if (User. identity. isAuthenticated) return RedirectToRoute (RouteName. room); return View ();} [ActionName ("enter"), HttpPost] public ActionR Esult EnterRoom (EnterRequest enterRequest) {if (! ModelState. isValid) return View (enterRequest); authSvc. authenticate (enterRequest. name); chatRoom. addParticipant ipant (enterRequest. name); return RedirectToRoute (RouteName. room);} [ActionName ("room"), HttpGet, Authorize] public ActionResult ShowRoom () {return View ();} [ActionName ("leave"), HttpGet, authorize] public ActionResult LeaveRoom () {authSvc. unauthenticate (); chatRoom. removeParticipant (User. id Entity. Name); return RedirectToRoute (RouteName. Enter);} [HttpPost, Authorize] public ActionResult Say (SayRequest sayRequest) {if (! ModelState. isValid) return Json (new SayResponse () {error = "the request is invalid. "}); chatRoom. addMessage (User. identity. name + "said:" + sayRequest. text); return Json (new SayResponse ();} [ActionName ("messages"), HttpPost, Authorize] public void GetMessagesAsync (GetMessagesRequest getMessagesRequest) {AsyncManager. outstandingOperations. increment (); if (! ModelState. isValid) {AsyncManager. parameters ["error"] = "The messages request was invalid. "; AsyncManager. parameters ["since"] = null; AsyncManager. parameters ["messages"] = null; AsyncManager. outstandingOperations. decrement (); return;} var since = dateTimeSvc. getCurrentDateTimeAsUtc (); if (! String. isNullOrEmpty (getMessagesRequest. since) since = DateTime. parse (getMessagesRequest. since ). toUniversalTime (); chatRoom. getMessages (since, (newMessages, timestamp) => {AsyncManager. parameters ["error"] = null; AsyncManager. parameters ["since"] = timestamp; AsyncManager. parameters ["messages"] = newMessages; AsyncManager. outstandingOperations. decrement () ;});} public ActionResult GetMessagesComp Leted (string error, DateTime? Since, IEnumerable <string> messages) {if (! String. isNullOrWhiteSpace (error) return Json (new GetMessagesResponse () {error = error}); var data = new GetMessagesResponse (); data. since = since. value. toString ("o"); data. messages = messages; return Json (data );}}}
Room. js
var since = "", errorCount = 0, MAX_ERRORS = 6;function addMessage(message, type) { $("#messagesSection > td").append("<div class='" + (type || "") + "'>" + message + "</div>")}function showError(error) { addMessage(error.toString(), "error");}function onSayFailed(XMLHttpRequest, textStatus, errorThrown) { showError("An unanticipated error occured during the say request: " + textStatus + "; " + errorThrown);}function onSay(data) { if (data.error) { showError("An error occurred while trying to say your message: " + data.error); return; }}function setSayHandler() { $("#Text").keypress(function (e) { if (e.keyCode == 13) { $("#sayForm").submit(); $("#Text").val(""); return false; } });}function retryGetMessages() { if (++errorCount > MAX_ERRORS) { showError("There have been too many errors. Please leave the chat room and re-enter."); } else { setTimeout(function () { getMessages(); }, Math.pow(2, errorCount) * 1000); }}function onMessagesFailed(XMLHttpRequest, textStatus, errorThrown) { showError("An unanticipated error occured during the messages request: " + textStatus + "; " + errorThrown); retryGetMessages();}function onMessages(data, textStatus, XMLHttpRequest) { if (data.error) { showError("An error occurred while trying to get messages: " + data.error); retryGetMessages(); return; } errorCount = 0; since = data.since; for (var n = 0; n < data.messages.length; n++) addMessage(data.messages[n]); setTimeout(function () { getMessages(); }, 0);}function getMessages() { $.ajax({ cache: false, type: "POST", dataType: "json", url: "/messages", data: { since: since }, error: onMessagesFailed, success: onMessages, timeout: 100000 });}
Chat view folder
Enter. cshtml
@ Model MvcAsyncChat. RequestModels. EnterRequest @ {View. Title = "Enter"; Layout = "~ /Views/Shared/_ Layout. cshtml ";}@ section Head {}< tr id =" enterSection "> <td>
Room. cshtml
@ Using MvcAsyncChat; @ using MvcAsyncChat. RequestModels; @ model SayRequest @ {View. Title = "Room"; Layout = "~ /Views/Shared/_ Layout. cshtml ";} @ section Head {<script src =" @ Url. Content ("~ /Scripts/room. js ") "> </script >}< tr id =" messagesSection "> <td> </tr> <tr id =" actionsSection "> <td> <label = "actionsList"> operation: </label> <ul id = "actionsList"> <li> @ Html. routeLink ("leave room", RouteName. leave) </li> </ul> @ using (Ajax. beginForm ("say", new {}, new AjaxOptions () {OnFailure = "onSayFailed", OnSuccess = "onSay", HttpMethod = "POST ",}, new {id = "sayForm"}) {@ Html. editorForModel () }</td> </tr> @ section PostScript {<script >$ (document ). ready (function () {$ ("# Text "). attr ("placeholder", "you say:"); $ ("# Text "). focus (); setSayHandler (); getMessages () ;}); </script>}
Running result:
The above is all the content of this article. I hope it will be helpful for your learning and support for helping customers.