当前位置: 移动技术网 > IT编程>开发语言>.net > ASP.NET MVC4异步聊天室的示例代码

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

2017年10月21日  | 移动技术网IT编程  | 我要评论

胎教英语,希琦杰西卡,代孕神父

本文介绍了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>
}

运行结果如图:

这里写图片描述

这里写图片描述

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

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网