asp.net ajax聊天室,ASP.NET MVC4异步聊天室的示例代码
本文介绍了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, 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 GetSince(DateTime since);
}
}
ICallbackQueue.cs
using System;
using System.Collections.Generic;
namespace MvcAsyncChat.Domain
{
public interface ICallbackQueue
{
void Enqueue(Action, DateTime> callback);
IEnumerable, DateTime>> DequeueAll();
IEnumerable, 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, 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>();
}
public IList> Messages { get; private set; }
public DateTime Add(string message)
{
var timestamp = DateTime.UtcNow;
Messages.Add(new Tuple(message, timestamp));
return timestamp;
}
public IEnumerable 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, DateTime>, DateTime>>();
}
public Queue, DateTime>, DateTime>> Callbacks { get; private set; }
public void Enqueue(Action, DateTime> callback)
{
Callbacks.Enqueue(new Tuple, DateTime>, DateTime>(callback, DateTime.UtcNow));
}
public IEnumerable, DateTime>> DequeueAll()
{
while (Callbacks.Count > 0)
yield return Callbacks.Dequeue().Item1;
}
public IEnumerable, 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 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? since,
IEnumerable 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("
")
}
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 {}
[MVC聊天]是使用ASP.NET MVC 3的异步聊天室
进入聊天室 @using(Html.BeginForm()) { @Html.EditorForModel() } |
@section PostScript {
$(document).ready(function() {
$("#Name").focus();
});
}
Room.cshtml
@using MvcAsyncChat;
@using MvcAsyncChat.RequestModels;
@model SayRequest
@{
View.Title = "Room";
Layout = "~/Views/Shared/_Layout.cshtml";
}
@section Head {
}
操作:
- @Html.RouteLink("离开房间", RouteName.Leave)
@using (Ajax.BeginForm("say", new { }, new AjaxOptions() {
OnFailure = "onSayFailed",
OnSuccess = "onSay",
HttpMethod = "POST", }, new { id = "sayForm"})) {
@Html.EditorForModel()
}
@section PostScript {
$(document).ready(function() {
$("#Text").attr("placeholder", "你说:");
$("#Text").focus();
setSayHandler();
getMessages();
});
}
运行结果如图:
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。
asp.net ajax聊天室,ASP.NET MVC4异步聊天室的示例代码相关推荐
- 《ASP.NET AJAX程序设计 第I卷 服务器端ASP.NET AJAX Extensions与ASP.NET AJAX Control Toolkit》目录(最终定稿)...
第一二卷都比较简单,特别是第一卷,讲的都是服务器端控件.第二卷是客户端部分,第三卷是高级内容,包括调试.性能.部署.控件开发.源代码结构.用户体验.心理学模型等等-- 第一卷争取在四月份出版,谢谢各位 ...
- asp.net ajax删除数据,Asp.net MVC 2 使用Ajax删除数据
一.新建一个Asp.net MVC 2 Empty Web Application. 二.添加一个名叫DataClasses1.dbml的Model,拖放Student表,最后如下图所示. 三.添加一 ...
- asp.net ajax 源码,asp.net+jquery+ajax简单留言板 v1.2
asp.netC#+jquery1.4.1 +ajax留言板程序说明 采用asp.net C#+ jquery1.4.1 +ajax的实现 主要用aspx文件请求 还可以用ashx处理 ajax返回类 ...
- MSDN Webcast“深入浅出ASP.NET AJAX系列”
课程: ASP.NET AJAX深入浅出系列课程(1):ASP.NET AJAX 概述(3月13日):对于ASP.NET AJAX的大致功能进行概述和演示,通过简单的演示让听众了解到ASP.NET A ...
- SharePoint 2010中的客户端AJAX应用——ASP.NET AJAX模板
WCF Data Services是SharePoint 2010中一个极具吸引力的新特性.然而,因为它的强大,直接对其进行编程仍然会有点痛苦.幸运的是,一个新的相关技术 -- ASP.Net AJA ...
- ASP.NET之父谈ASP.NET AJAX
ASP.NET之父SCOTT GUTHRIE强烈推荐的ASP.NET AJAX著作 世界各地数百万专业开发人员每天都在使用ASP.NET.全世界最成功的一些网站和应用都以它为后盾,每天还有成千上万的新 ...
- ASP.NET AJAX入门系列(1):概述
经常关注我的Blog的朋友可能注意到了,在我Blog的左边系列文章中,已经移除了对Atlas学习手记系列文章的推荐,因为随着ASP.NET AJAX 1.0 Beta版的发布,它们已经不再适用,为了不 ...
- Msdn 杂志 asp.net ajax 文章汇集
asp.net ajax 充分利用客户端 JavaScript.DHTML 和 XMLHttpRequest 对象.其目的是帮助开发人员创建更具交互性的支持 AJAX 的 Web 应用程序 ASP.N ...
- [翻译]ASP.NET AJAX与SharePoint的集成
原文: Integrating ASP.NET AJAX with SharePoint 来自微软SharePoint Team Blog Microsoft ASP.NET AJAX 1.0: 一点 ...
最新文章
- malloc和new出来的地址都是虚拟地址 你就说内存管理单元怎么可能让你直接操作硬件内存地址!...
- gunicorn之日志详细配置
- 【教程】超详细的虚拟无线控制器安装教程
- 网银无法登录解决办法
- java 中导出word后压缩文件_Java批量导出word压缩后的zip文件案例
- Machine Learning Mastery 博客文章翻译:深度学习与 Keras
- 虚拟机Ubuntu20.04.2LTS卸载python3.8出现tty1-tty6循环登录,无法进入图形化界面,乱码(亲测)
- SVM原理以及Tensorflow 实现SVM分类(附代码)
- 2021牛客暑期多校训练营3,签到题BEFJ
- 软件需求工程与UML建模第十二周作业
- HTML超连接(a标记)
- Q 语言 -- 赋值表达式
- 罗永浩写给俞敏洪的信
- QT图形显示和处理6
- 第7章概率和样本:样本均值的分布
- 淘宝/天猫关键词搜索采集接口分析商品价格走势(商品列表,商品销量,商品价格,分类ID采集精准商品数据)接口代码对接流程
- SK-learn实现k近邻算法【准确率随k值的变化】-------莺尾花种类预测
- 基于百度AI平台的植物识别系统 新手适用!!
- 左右两侧浮动广告代码
- IOS单例模式及单例模式的优缺点
热门文章
- 华为提出十大数学挑战!解出一个就是年薪百万!
- 每日一皮:程序员穿着图解析
- Spring Boot 2.x基础教程:使用JdbcTemplate访问MySQL数据库
- MySQL百万级数据分页查询及优化
- 死磕Java并发:J.U.C之阻塞队列:PriorityBlockingQueue
- Spring Cloud实战小贴士:Ribbon的饥饿加载(eager-load)模式
- 都在说微服务,那么微服务的反模式和陷阱是什么(三)
- mysql导出停机_MySQL自动停机的问题处理实战记录
- asp.net oracle优化,[转]ASP.NET性能优化
- insightface mxnet训练 out of Memory