1

这是场景-

我有一个通过 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 获取请求。问题是当我对 GetFileProcessStatus 执行 ajax 获取请求时,Session["UserMessage"] 始终为空。我也尝试过 TempData 而不是 Session 具有相同的结果。根据我对 Session 的了解,我在这里尝试完成的工作是不可行的,因为 Session 的优先级是给第一个调用者的。在我的情况下,第一个调用者是 UploadAndProcessFile。我希望这是有道理的,并且有人可以提供帮助!

谢谢-JD

4

1 回答 1

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 });
    }
于 2013-10-22T22:43:53.560 回答