本文介绍了ASP.NET MVC4异步聊天室的示例代码,分享给大家,具体如下:
类图:
Domain层
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 IDateTimeSvc dateTimeSvc; readonly IMessageRepo messageRepo; public ChatRoom( ICallbackQueue callbackQueue, IDateTimeSvc dateTimeSvc, IMessageRepo 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(string name) { AddMessage(string.Format("{0} 已进入房间.", 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文件夹实体类
EnterRequest.cs
using System; using System.ComponentModel; using System.ComponentModel.DataAnnotations; namespace MvcAsyncChat.RequestModels { public class EnterRequest { [DisplayName("名称")] [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文件夹实体类
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 IDateTimeSvc 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 ActionResult EnterRoom(EnterRequest enterRequest) { if (!ModelState.IsValid) return View(enterRequest); authSvc.Authenticate(enterRequest.Name); chatRoom.AddParticipant(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.Identity.Name); return RedirectToRoute(RouteName.Enter); } [HttpPost, Authorize] public ActionResult Say(SayRequest sayRequest) { if (!ModelState.IsValid) return Json(new SayResponse() { error = "该请求无效." }); chatRoom.AddMessage(User.Identity.Name+" 说:"+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 GetMessagesCompleted( string error, DateTime"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视图文件夹
Enter.cshtml
@model MvcAsyncChat.RequestModels.EnterRequest @{ View.Title = "Enter"; Layout = "~/Views/Shared/_Layout.cshtml"; } @section Head {} <tr id="enterSection"> <td> <h2>[MVC聊天]是使用ASP.NET MVC 3的异步聊天室 <table> <tr> <td class="form-container"> <fieldset> <legend>进入聊天室</legend> @using(Html.BeginForm()) { @Html.EditorForModel() <input type="submit" value="Enter" /> } </fieldset> </td> </tr> </table> </td> </tr> @section PostScript { <script> $(document).ready(function() { $("#Name").focus(); }); </script> }
Room.cshtml
广告合作:本站广告合作请联系QQ:858582 申请时备注:广告合作(否则不回)
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
暂无评论...
RTX 5090要首发 性能要翻倍!三星展示GDDR7显存
三星在GTC上展示了专为下一代游戏GPU设计的GDDR7内存。
首次推出的GDDR7内存模块密度为16GB,每个模块容量为2GB。其速度预设为32 Gbps(PAM3),但也可以降至28 Gbps,以提高产量和初始阶段的整体性能和成本效益。
据三星表示,GDDR7内存的能效将提高20%,同时工作电压仅为1.1V,低于标准的1.2V。通过采用更新的封装材料和优化的电路设计,使得在高速运行时的发热量降低,GDDR7的热阻比GDDR6降低了70%。
更新日志
2024年11月30日
2024年11月30日
- 凤飞飞《我们的主题曲》飞跃制作[正版原抓WAV+CUE]
- 刘嘉亮《亮情歌2》[WAV+CUE][1G]
- 红馆40·谭咏麟《歌者恋歌浓情30年演唱会》3CD[低速原抓WAV+CUE][1.8G]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[320K/MP3][193.25MB]
- 【轻音乐】曼托凡尼乐团《精选辑》2CD.1998[FLAC+CUE整轨]
- 邝美云《心中有爱》1989年香港DMIJP版1MTO东芝首版[WAV+CUE]
- 群星《情叹-发烧女声DSD》天籁女声发烧碟[WAV+CUE]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[FLAC/分轨][748.03MB]
- 理想混蛋《Origin Sessions》[320K/MP3][37.47MB]
- 公馆青少年《我其实一点都不酷》[320K/MP3][78.78MB]
- 群星《情叹-发烧男声DSD》最值得珍藏的完美男声[WAV+CUE]
- 群星《国韵飘香·贵妃醉酒HQCD黑胶王》2CD[WAV]
- 卫兰《DAUGHTER》【低速原抓WAV+CUE】
- 公馆青少年《我其实一点都不酷》[FLAC/分轨][398.22MB]
- ZWEI《迟暮的花 (Explicit)》[320K/MP3][57.16MB]