虚位以待(AD)
虚位以待(AD)
首页 > 网络编程 > ASP.NET > ASP.NET MVC4异步聊天室的示例代码

ASP.NET MVC4异步聊天室的示例代码
类别:ASP.NET   作者:码皇   来源:互联网   点击:

这篇文章主要介绍了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<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? 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视图文件夹

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

    @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></td></tr><tr id="actionsSection"> <td> <label for="actionsList">操作:</label> <ul id="actionsList"> <li>@Html.RouteLink("离开房间", 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", "你说:");
    $("#Text").focus();
    setSayHandler();
    getMessages();
    }
    );
    </script>}

运行结果如图:

这里写图片描述

这里写图片描述

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

您可能感兴趣的文章:

  • 详解Asp.Net MVC的Bundle捆绑
  • ASP.NET MVC下自定义错误页和展示错误页的方式
  • Asp.net MVC scheduler的实现方法详解
  • Asp.net mvc验证用户登录之Forms实现详解
  • asp.net mvc webapi 实用的接口加密方法示例
  • ASP.NET MVC API 接口验证的示例代码
  • asp.net mvc CodeFirst模式数据库迁移步骤详解
  • IIS部署asp.net mvc网站的方法
  • Asp.Net中MVC缓存详解
相关热词搜索: ASP NET MVC4异步聊天室 ASP NET MVC4异步