Reputation: 374
Here is the scenario-
I have a form that uploads a file to a Action via Ajax POST. Once the file is uploaded it is processed and the data is inserted into a database. This can take some time so I would like to be able to send messages back to the user letting the user know at what step in the process the file is at. Basically what I have right now is:
[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);
}
On the client side I post the form via ajax to the UploadAndProcessFile Action and then have a function that continually does an ajax get request to GetFileProcessStatus. The problem is that when I do the ajax get reqeust to GetFileProcessStatus the Session["UserMessage"] is always null. I have also tried TempData instead of the Session with the same results. From what I understand about Session, what I am trying to accomplish here is not doable because the precedence for Session is given to the first caller. In my case the first caller would be UploadAndProcessFile. I hope this make sense and that someone can help!
Thanks - JD
Upvotes: 1
Views: 350
Reputation: 1734
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 });
}
Upvotes: 2