欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

ASP.NET MVC4异步聊天室的示例代码

程序员文章站 2022-06-23 10:49:43
本文介绍了asp.net mvc4异步聊天室的示例代码,分享给大家,具体如下: 类图: domain层 ichatroom.cs using syste...

本文介绍了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 MVC4异步聊天室的示例代码

ASP.NET MVC4异步聊天室的示例代码

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