1

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?

Mohammed Ismail
  • 196
  • 1
  • 15

0 Answers0