2

ASP.NET MVC3 Webアプリケーションに、現在サイトを閲覧しているユーザーの数を表示する小さなメッセージを追加したいと思います。

私は現在、Global.asax内の静的プロパティをインクリメントまたはデクリメントするためにアプリケーションイベントを使用Session_Startしています。Session_End

これは機能しますが、正確ではありません。私のセッションタイムアウトは20分に設定されているので、更新の間に大きな遅延があります。

これを行うためのよりエレガントで正確な方法はありますか?

Session.Abandon()javascriptイベントを単純に実行するAJAXを介してアクションを呼び出すことを考えましたwindow.onbeforeunloadが、これはユーザーがページを変更するたびに呼び出されます。ユーザーがいつブラウザを閉じるか、ドメインを離れるかを判断する方法はありますか?

ヒント、コメント、コード例は大歓迎です!

現在のコードの関連部分は次のとおりです。

public class MvcApplication : System.Web.HttpApplication
{
    public static int UsersConnected { get; set; }

    protected void Session_Start(object sender, EventArgs e)
    {
        Application.Lock();
        UsersConnected++;
        Application.UnLock();
    }

    protected void Session_End(object sender, EventArgs e)
    {
        Application.Lock();
        UsersConnected--;
        Application.UnLock();
    }

    ...
}
4

2 に答える 2

2

さて、これは少しトリッキーでしたが、「大丈夫」な解決策がありました。

まず、クライアントの IP アドレスと最後のポーリング日付を格納する静的辞書を Global.asaxに作成しました。

public class MvcApplication : System.Web.HttpApplication
{
   public static Dictionary<string, DateTime> ConnectedtUsers { get; set; }

   protected void Application_Start()
   {
        AreaRegistration.RegisterAllAreas();
        RegisterGlobalFilters(GlobalFilters.Filters);
        RegisterRoutes(RouteTable.Routes);
        ConnectedtUsers = new Dictionary<string, DateTime>();
   }

   ...
}

次に、CommonsControllerで、新しいクライアントを追加し、過去 30 秒間ポーリングされていないクライアントを削除し、既に登録されているクライアントのポーリング日付を更新するこのアクションを作成しました。

public class CommonsController : Controller
{
    ...

    public JsonResult UserConnected()
    {
        string ip = Request.UserHostAddress;

        if (MvcApplication.ConnectedtUsers.ContainsKey(ip))
        {
            MvcApplication.ConnectedtUsers[ip] = DateTime.Now;
        }
        else
        {
            MvcApplication.ConnectedtUsers.Add(ip, DateTime.Now);
        }

        int connected = MvcApplication.ConnectedtUsers.Where(c => c.Value.AddSeconds(30d) > DateTime.Now).Count();

        foreach (string key in MvcApplication.ConnectedtUsers.Where(c => c.Value.AddSeconds(30d) < DateTime.Now).Select(c => c.Key))
        {
            MvcApplication.ConnectedtUsers.Remove(key);
        }

        return Json(new { count = connected }, JsonRequestBehavior.AllowGet);
    }
}

最後に、レイアウト ページに、30 秒ごとにアクションを呼び出して結果をスパンで出力する次のコードを追加しました。

<span id="connectedUsers"></span>

<script type="text/javascript">
    function PollUsers()
    {
        $(function() {
            $.getJSON("/Commons/UserConnected", function(json){ $('#connectedUsers').text(json.count + " user(s) connected")}); 
        });
    }

    setInterval(PollUsers, 30000);
</script>

それほど正確ではないかもしれませんエレガントではないかもしれませんが、うまくいきます。もちろん、同じ IP からの複数のユーザーは 1 人のユーザーとしてカウントされます。しかし、これは私がこれまでに試した中で最高のソリューションです。

于 2012-07-21T14:48:45.387 に答える
0

unload body イベントで javascript から webmethod を呼び出すことができます。 http://www.codeproject.com/Tips/89661/Execute-server-side-code-on-close-of-a-browser よろしくお願いします

于 2012-07-21T14:27:17.840 に答える