La soluzione al problema che stavo avendo è un po 'complessa, ma funziona in modo simile alla correzione IFrame. Il risultato è una finestra pop-up che gestisce l'elaborazione, consentendo all'utente di continuare la navigazione all'interno del sito.
Il file viene inviato al server (controller UploadCSV), una pagina di successo viene restituita con un po 'di JavaScript per gestire il primo avvio dell'elaborazione. Quando l'utente fa clic su "Inizia elaborazione", viene aperta una nuova finestra (ImportProcessing/Index) che carica lo stato iniziale (eseguendo il ciclo di un intervallo che recupera gli aggiornamenti di stato) e quindi effettua una chiamata all'azione "Avvia elaborazione", dando il via al processo di elaborazione.
La classe "FileProcessor" che sto utilizzando è contenuta in una variabile di dizionario statica all'interno del controller ImportProcessing; consentendo i risultati dello stato in base alla chiave. Il FileProcessor viene prontamente rimosso dopo che l'operazione è stata completata o si è verificato un errore.
Carica Controller:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult UploadCSV(HttpPostedFileBase uploadFile)
{
var filePath = string.Empty;
if (uploadFile.ContentLength <= 0)
{
return View();
}
filePath = Path.Combine(Server.MapPath(this.UploadPath), "DeptartmentName",Path.GetFileName(uploadFile.FileName));
if (new FileInfo(filePath).Exists)
{
ViewBag.ErrorMessage =
"The file currently exists on the server. Please rename the file you are trying to upload, delete the file from the server," +
"or contact IT if you are unsure of what to do.";
return View();
}
else
{
uploadFile.SaveAs(filePath);
return RedirectToAction("UploadSuccess", new {fileName = uploadFile.FileName, processType = "sonar"});
}
}
[HttpGet]
public ActionResult UploadSuccess(string fileName, string processType)
{
ViewBag.FileName = fileName;
ViewBag.PType = processType;
return View();
}
Carica Successo HTML:
@{
ViewBag.Title = "UploadSuccess";
}
<h2>File was uploaded successfully</h2>
<p>Your file was uploaded to the server and is now ready to be processed. To begin processing this file, click the "Process File" button below.
</p>
<button id="beginProcess" >Process File</button>
<script type="text/javascript">
$(function() {
$("#beginProcess").click(BeginProcess);
function BeginProcess() {
window.open("/SomeController/ImportProcessing/[email protected]&[email protected]", "ProcessStatusWin", "width=400, height=250, status=0, toolbar=0, scrollbars=0, resizable=0");
window.location = "/Department/Import/Index";
}
});
</script>
Una volta che questa nuova finestra si apre, l'elaborazione dei file inizia. Gli aggiornamenti vengono recuperati da una classe FileProcessing personalizzata.
ImportProcessing Controller:
public ActionResult Index(string fileName, string type)
{
ViewBag.File = fileName;
ViewBag.PType = type;
switch (type)
{
case "somematch":
if (!_fileProcessors.ContainsKey(fileName)) _fileProcessors.Add(fileName, new SonarCsvProcessor(Path.Combine(Server.MapPath(this.UploadPath), "DepartmentName", fileName), true));
break;
default:
break;
}
return PartialView();
}
ImportProcessing Indice:
@{
ViewBag.Title = "File Processing Status";
}
@Scripts.Render("~/Scripts/jquery-1.8.2.js")
<div id="StatusWrapper">
<div id="statusWrap"></div>
</div>
<script type="text/javascript">
$(function() {
$.ajax({
url: "GetStatusPage",
data: { fileName: "@ViewBag.File" },
type: "GET",
success: StartStatusProcess,
error: function() {
$("#statusWrap").html("<h3>Unable to load status checker</h3>");
}
});
function StartStatusProcess(result) {
$("#statusWrap").html(result);
$.ajax({
url: "StartProcessing",
data: { fileName: "@ViewBag.File" },
type: "GET",
success: function (data) {
var messag = 'Processing complete!\n Added ' + data.CurrentRecord + ' of ' + data.TotalRecords + " records in " + data.ElapsedTime + " seconds";
$("#statusWrap #message").html(messag);
$("#statusWrap #progressBar").attr({ value: 100, max: 100 });
setTimeout(function() {
window.close();
}, 5000);
},
error: function (xhr, status) {
alert("Error processing file");
}
});
}
});
</script>
Infine Status Checker html:
@{
ViewBag.Title = "GetStatusPage";
}
<h2>Current Processing Status</h2>
<h5>Processing: @ViewBag.File</h5>
<h5>Updated: <span id="processUpdated"></span></h5>
<span id="message"></span>
<br />
<progress id="progressBar"></progress>
<script type="text/javascript">
$(function() {
var checker = undefined;
GetStatus();
function GetStatus() {
if (checker == undefined) {
checker = setInterval(GetStatus, 3000);
}
$.ajax({
url: "[email protected]",
type: "GET",
success: function (result) {
result = result || {
Available: false,
Status: {
TotalRecords: -1,
CurrentRecord: -1,
ElapsedTime: -1,
Message: "No status data returned"
}
};
if (result.Available == true) {
$("#progressBar").attr({ max: result.Status.TotalRecords, value: result.Status.CurrentRecord });
$("#processUpdated").text(result.Status.Updated);
$("#message").text(result.Status.Message);
} else {
clearInterval(checker);
}
},
error: function() {
$("#statusWrap").html("<h3>Unable to load status checker</h3>");
clearInterval(checker);
}
});
}
});
</script>
grazie per l'input, ho intenzione di giocare con questo per un po 'e vedere cosa ne esce. Mi assicurerò di accettare questa risposta se funziona per me. – TNCodeMonkey
Ho cercato in giro cercando di trovare il modo migliore per avvicinarmi usando questo metodo, ma ho capito che non era quello di cui avevo bisogno. Non rimedierebbe al fatto che il post rimarrà aperto fino a quando l'azione non sarà tornata, indipendentemente dal threading. Ho aggiunto una risposta in fondo con la mia soluzione. – TNCodeMonkey