MVC3,AJAX,Session和多个请求

时间:2013-10-22 21:58:12

标签: ajax asp.net-mvc-3 session ajax-request

以下是情景 -

我有一个表单,通过Ajax POST将文件上传到Action。文件上传后,将对其进行处理,并将数据插入数据库。这可能需要一些时间,所以我希望能够将消息发送回用户,让用户知道文件所处的过程中的哪一步。基本上我现在所拥有的是:

[HttpPost]
public void UploadAndProcessFile()
{
   Session["UserMessage"] = "Start";
   // Do some stuff
   Session["UserMessage"] = "25% done";
   // Do some stuff
   Session["UserMessage"] = "50% done";
   // Do some stuff
   Session["UserMessage"] = "75% done";
   // Do some stuff
   Session["UserMessage"] = "Completed!";
}

[HttpGet]
putlic JsonResults GetFileProcessStatus()
{
  string returnMessage = (Session["UserMessage"] ?? "");
  return Json(returnMessage, JsonRequestBehavior.AllowGet);
}

在客户端,我通过ajax将表单发布到UploadAndProcessFile Action,然后有一个函数不断向GetFileProcessStatus发出ajax get请求。问题是,当我执行ajax get getqeust到GetFileProcessStatus时,Session [“UserMessage”]始终为null。我也尝试过TempData而不是Session,结果相同。根据我对Session的理解,我在这里想要完成的是不可行的,因为Session的优先级是给第一个调用者的。在我的情况下,第一个调用者是UploadAndProcessFile。我希望这是有道理的,有人可以提供帮助!

谢谢 - JD

1 个答案:

答案 0 :(得分:2)

class ParameterForMyProcess
    {
        public string criteria { get; set; }
        public Guid processID { get; set; }
        public HttpContext context { get; set; }
    }

    private Guid StartProcess(string criteria)
    {
        // we will use this id later to get status updates on this specific process.
        var processID = Guid.NewGuid();

        // the thread we are starting can only take one parameter,
        // so we create a container for all the data we might want to use
        // and pass that in as the single parameter into the process.

        var parameter = new ParameterForMyProcess()
            {
                criteria = criteria,
                processID = processID,
                context = System.Web.HttpContext.Current
            };

        var thread = new System.Threading.Thread(
            new System.Threading.ParameterizedThreadStart(CreateProcess));

        thread.Start(parameter);
        return processID;
    }

private void CreateProcess(object parameter)
    {
        // cast the object to our parameter type
        var myParameter = parameter as ParameterForMyProcess;

        // you now have access to some data if you wish
        var criteria = myParameter.criteria;

        // process ID to report progress with
        var processID = myParameter.processID;

        System.Web.HttpContext.Current = myParameter.context;

        // Do something

        updateStatus(processID, "Hello World");
     }

     private void updateStatus(Guid processID, string status)
    {
        // store the status in the http cache.  

        var key = "CreateProcess:" + processID.ToString();
        var cache = System.Web.HttpContext.Current.Cache;
        var oldStatus = cache[key];
        var newStatus = oldStatus + "<br/>" + status;
        cache[key] = newStatus;

        // this implementation relies on the browser to trigger an action which will clean up this data from the cache.
        // there is no guarantee this will be triggered (user closes browser, etc), 
        // but since the cache has means for eventually removing this data, this isn't a big risk.
    }

    public JsonResult GetProcessStatus(string processID)
    {
        var status = System.Web.HttpContext.Current.Cache["CreateProcess:" + processID.ToString()];
        return Json(new { status = status });
    }