通过AJAX调用的控制器之间的共享会话状态访问

时间:2011-01-31 05:57:11

标签: asp.net-mvc asp.net-mvc-3

我正在尝试为AsyncController实现的长期运行请求提供进度监视机制。一个网页调用(通过JQuery $.post)以下控制器上的异步StartTask操作......

[NoAsyncTimeout]
public class TaskController: AsyncController
{
   [HttpPost]
   public void StartTaskAsync()
   {
      AsyncManager.OutstandingOperations.Increment();
      Session["progress"] = "in progress";
      Task.Factory.StartNew(DoIt);
   }

   public ActionResult StartTaskCompleted()
   {
      return Json(new {redirectUrl = Url.Action("TaskComplete", "First")});
   }

   private void DoIt()
   {
      try
      {
         // Long-running stuff takes place here, including updating 
         // Session["progress"].
      }
      finally
      {
         AsyncManager.OutstandingOperations.Decrement();
      }
   }
}

同一个网页设置一个2秒的计时器(通过window.setInterval)来调用对会话具有只读访问权限的以下控制器(通过JQuery $.getJSON)...

[SessionState(SessionStateBehavior.ReadOnly)]
public class ProgressController: Controller
{
    [HttpGet]
    public ActionResult Current()
    {
       var data = Session["progress"];
       return Json(data, JsonRequestBehavior.AllowGet);
    }
}

getJSON返回后调用的函数更新DIV以显示当前进度。最终,会话将在会话中通过“长时间运行的东西发生在这里”代码进行更新,但因为调用ProgressController.Current()会在会话中找不到任何数据并始终返回null。

我曾假设从同一个浏览器发送到同一个IIS服务器的JQuery AJAX请求最终会使用相同的会话,但似乎没有。我是否需要在这些$ .post和$ .getJSON调用上显式设置ASP.NET会话密钥?或者是不可能以这种方式在控制器之间共享会话状态(即使有一个具有R / O访问权限)(我可以回退到具有应用程序状态和GUID的轻微hacky解决方案)。

1 个答案:

答案 0 :(得分:0)

这是正常行为。您的StartTask操作会一直阻止,直到完成为止。在DoIt方法执行完毕之前,它不会返回任何响应。我想这就是你用AJAX $.post调用它的原因。问题是,当此方法运行并写入会话时,来自同一会话的所有其他请求将由ASP.NET引擎排队。您无法同时在会话中进行写入和读取。除了会话之外,您还必须为进度数据找到另一个线程安全存储。