I recently converted one of my controllers to a background Task, which returns an HTTPResponseMessage once the thread is completed. The issue i am facing is to get the download to pop up after the task is done. I have implemented SignalR as well for tracking the progress. Here is my controller code:
public async Task<IHttpActionResult> GetReportaync([FromUri] ReportRequestViewModel request)
{
var token = UnitOfWork.Start();
HostingEnvironment.QueueBackgroundWorkItem(CancellationToken =>
{
using (token)
{
try
{
HubFunctions.UpdateReportProgress(username, status);
var parameters = request.ToReportParams();
var report = ReportFactory.CreateReport(request.ReportExportType, IsVA());
var docStream = report.BuildReport(parameters);
if (request.SaveReport)
{
SaveDocumentToAmazon(request, report.FileName, docStream);
}
var GeneratedReport = GetFileAsResponseMessage(docStream.ToArray(), report.FileName, true);
ReportCacheDto generateReportDto1 = new ReportCacheDto()
{
Report = GeneratedReport,
Status = CacheConstants.Progress.Completed.ToString()
};
bool completed = SaveCacheReportProgress(key, generateReportDto1);
Request.CreateResponse(GeneratedReport);
HubFunctions.UpdateReportResult(new GenerateReportDto() { Message = "Import Completed", Success = true, Report = GeneratedReport }, username);
}
catch(Exception e)
{
LogHandler.LogError("An error occured", e);
Request.CreateResponse(HttpStatusCode.InternalServerError, e);
HubFunctions.UpdateReportResult(new GenerateReportDto() { Message = "Import Failed", Success = false, Report = Report }, username);
}
}
});
return Ok(new GenerateReportDto
{
Message = "Generate Started",
Success = true
});
}
Next is the return method called GetFileasResponse:
protected HttpResponseMessage GetFileAsResponseMessage(byte[] fileData, string filename, bool download = false)
{
var response = new HttpResponseMessage(HttpStatusCode.OK);
fileContent = fileData;
string fileType = string.Empty;
string extension = Path.GetExtension(filename.ToLower());
if(mediaTypeHeaderValueTypes.ContainsKey(extension))
{
fileType = mediaTypeHeaderValueTypes[extension].ToString();
}
else
{
fileType = "application/octet-stream";
}
Action<Stream, HttpContent, TransportContext> writeToStream = WriteToStream;
response.Content = new PushStreamContent(writeToStream, new MediaTypeHeaderValue(fileType));
var dispositionHeader = download ? "attachment" : "inline";
response.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue(dispositionHeader)
{
/*
* See here:
* https://stackoverflow.com/questions/93551/how-to-encode-the-filename-parameter-of-content-disposition-header-in-http
* and here:
* https://msdn.microsoft.com/en-us/library/4fkewx0t(v=vs.110).aspx
*/
FileName = HttpUtility.UrlPathEncode(filename) // encodes " " as %20 which is what we want.
};
return response;
}
The issue really stems from the front end, because i can return the response file in my console log but i dont know how to have it to pop up as a download. Here is what i have attempted
ScorecardReportVM.prototype.ConnectToSignalRHub_ReportResult = function () {
var self = this;
var hub = $.connection.ReportResult;
hub.client.UpdateStatus = function (response) {
self.SetImportRunning(false);
var link = document.createElement('a');
link.href = response.Report;
document.body.appendChild(link);
link.click();
console.log(response);
};
};
Essentially signalR once completed returns:
public bool Success { get; set; }
public string Message { get; set; }
public HttpResponseMessage Report { get; set; }
Now my issue is how do i get the Report parameter to pop up as a download?