在MVC 3中禁用Session以允许多个AJAX调用

时间:2012-02-11 14:57:53

标签: ajax asp.net-mvc-3

同时执行多个Ajax调用会导致我的MVC Web应用程序被阻止。我一直在阅读,我找到了两个有同样问题的主题

Why would multiple simultaneous AJAX calls to the same ASP.NET MVC action cause the browser to block?

Asynchronous Controller is blocking requests in ASP.NET MVC through jQuery

他们的解决方案是使用 ControllerSessionStateAttribute 禁用会话。我尝试使用该属性,但我的代码仍在阻止。您可以使用以下代码重现创建新MVC3 Web应用程序的问题

@{
    ViewBag.Title = "Home Page";
}

<h2>@ViewBag.Message</h2>
<p>
    Example of error when calling multiple AJAX, try click quickly on both buttons until the server get blocked.
</p>
<button onclick="cuelga++;SetCallWaiting(cuelga);">Set a call waiting in the server</button><button onclick="libera++;ReleaseEveryone(libera);">Release all calls in the server</button>
<div id="text"></div>
<script type="text/javascript">
    var cuelga = 0;
    var libera =0;

        function ReleaseEveryone(number) {
            var url =  "/Home/ReleaseEveryone/";
            $.post(url, { "id": number },
                ShowResult1, "json");

        };

        function SetCallWaiting(number) {

            var url = "/Home/SetACallWaiting/";
            $.post(url, { "id": number },
                ShowResult, "json");
        };

        function ShowResult (data) {
            $("#text").append(' [The call waiting number ' + data[0] + ' come back ] ');
            /* When we come back we also add a new extra call waiting with number 1000 to   make it diferent */
            SetCallWaiting(1000);
        };
        function ShowResult1(data) {
            $("#text").append(' [The release call number ' + data[0] + ' come back ] ');
        };
</script>

这是HomeController

using System;
using System.Collections.Generic;
using System.Web.Mvc;
using System.Threading;
using System.Web.SessionState;

namespace ErrorExample.Controllers
{
    [SessionState(SessionStateBehavior.Disabled)]
    public class HomeController : Controller
    {
        private static List<EventWaitHandle> m_pool = new List<EventWaitHandle>();
        private static object myLock = new object();


        public ActionResult Index()
        {
            ViewBag.Message = "Welcome to ASP.NET MVC!";

            return View();
        }

        public ActionResult About()
        {
            return View();
        }

        [HttpPost]
        public JsonResult SetACallWaiting()
        {
            EventWaitHandle myeve;
            lock (myLock)
            {
                myeve = new EventWaitHandle(false, EventResetMode.ManualReset);
                m_pool.Add(myeve);
            }
            myeve.WaitOne();

            var topic = HttpContext.Request.Form[0];
            return Json(new object[] { topic });
        }

        [HttpPost]
        public JsonResult ReleaseEveryone()
        {
            try
            {
                lock (myLock)
                {
                    foreach (var eventWaitHandle in m_pool)
                    {
                        eventWaitHandle.Set();
                    }
                    m_pool.Clear();
                }
                var topic = HttpContext.Request.Form[0];
                return Json(new object[] { topic });
            }
            catch ( Exception )
            {
                return Json( new object[] { "Error" } );
            }
        }
    }
}

非常感谢您提前。

1 个答案:

答案 0 :(得分:0)

我认为这个问题实际上与SessionState无关。 每个浏览器仅向域发出有限数量的并发请求 - 有关详细信息,请参阅this article

我认为问题是由于如果您启动多个“SetACallWaiting”请求,您会遇到浏览器甚至不会将请求发送到服务器直到先前的请求未得到答复的情况 - 因此请求浏览器不发送“ReleaseEveryone”。因此,您将获得锁定行为。

此外,您发布的代码示例可能存在问题 - “SetCallWaiting(1000);”函数ShowResult中的行。通过此调用,您实际上不会减少等待请求的数量,因为每次发布请求时,都会再次重新创建(我不确定这是否是您想要的)。

要测试此行为,请查看浏览器发送的请求并在控制器的操作中设置断点,并查看它对各种请求的行为方式。