label not updated in System.Threading.ThreadAbortException - c#

In my page i am trying to download file. THe file is downloaded successfully but i get System.Threading.ThreadAbortException. So i handled that in my try Catch Block and set the error lable to blank but it doesnt get updated in page.
catch (System.Threading.ThreadAbortException)
{
lblErrorMsg.Text = "dfdf";
}
catch (Exception ex)
{
lblErrorMsg.Text = "Error while processing you request :<br> Erorr Description : " + ex.Message;
}
This is my Write file function
public static void WriteFile(string nameOfFile, string fileContent, HttpResponse writer)
{
writer.ClearHeaders();
writer.ClearContent();
writer.ContentType = "text/xml";
writer.AppendHeader("Content-Disposition", "attachment; filename=" + nameOfFile);
writer.Write(fileContent);
writer.Flush();
writer.End();
}
Can someone tell why label is not set to blank even though it comes under the Catch Block of system.thread.threadabortexceptiopn when i debug code ?

ThreadAbortException happens because you close the Response prematurely, by calling End() method of Response object.
This also explains why it's too late to write on the page content. It's not a very annoying error but it would be better to handle it cleanly.
Just check these answers Why Response.Redirect causes System.Threading.ThreadAbortException? or How to Avoid Response.End() "Thread was being aborted" Exception during the Excel file download and other answers related to Response and ThreadAbortException to understand it and handle properly by writing a better code for file download, according your usage.
Also please note that doesn't make a great sense to have both a completely rewritten Response stream for a page and some content on it, like a Label.

Related

Generated Docx File is Corrupt - C#

I am creating a docx file with my app, and I get stuck with the Response.End(). I get this error:
Thread was being aborted
I get this error, but the file is still created anyway. When I try to open the file it's always corrupted. I am not having any success writing the .docx file. Please let me know what I am doing wrong.
HttpContext.Current.Response.ContentType = "application/vnd.openxmlformats-officedocument.wordprocessingml.document; charset=utf-8";
HttpContext.Current.Response.AddHeader("content-disposition", String.Format("attachment;filename={0}", "mydoc.docx"));
HttpContext.Current.Response.BinaryWrite(ourString);
HttpContext.Current.Response.Flush();
HttpContext.Current.Response.End();
Note, you should not place Response.End inside the try-catch block because it's expected that it will throw that exception.
See the HttpResponse.End method's remarks:
To mimic the behavior of the End method in ASP, this method tries to
raise a ThreadAbortException exception.
You can avoid this by using the following:
var response = HttpContext.Current.Response;
response.Clear();
response.ContentType = "application/vnd.openxmlformats-officedocument.wordprocessingml.document;
response.AddHeader("Content-Disposition", "attachment;filename=mydoc.docx");
response.OutputStream.Write(ourString, 0, ourString.Length);
response.Flush();
HttpContext.Current.ApplicationInstance.CompleteRequest();
Note, in the above code I'm presuming that your ourString variable is byte array because you were passing it to the BinaryWrite method in your snippet code.
However, this name leads me to believe that you have just converted your string to byte[], is that correct?
If it is, note that this is not a valid DOCX file, DOCX format is not a plain text, you need to write it correctly using Office Open XML format (WordprocessingML).

Error when attempting to Export data to Excel.

I have a button that exports data from telerik's RadGrid into an Excel document.
However, I am encountering the following error when I attempt to export:
[System.Threading.ThreadAbortException]:
{Unable to evaluate expression because the code is optimized or a native frame is on top of the call stack.}
Here's my code:
private void GenerateFile(object structure, string fileName)
{
Workbook workbook = structure as Workbook;
var formatProvider = new XlsxFormatProvider();
try
{
using (MemoryTributary ms = new MemoryTributary())
{
Response.ClearHeaders();
Response.ClearContent();
Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
Response.AddHeader("content-disposition", "attachment; filename=" + fileName);
formatProvider.Export(workbook, ms);
ms.Position = 0;
ms.WriteTo(Response.OutputStream);
Response.End();
}
}
catch (System.OutOfMemoryException ex)
{
}
}
}
I have tried the following solutions based on posts I have found online that dealt with the same issue, none of the solutions have worked:
Change "Response.End()" to "HttpContext.Current.ApplicationInstance.CompleteRequest()"
Change "Response.End()" to "HttpContext.Current.Response.End()"
Move "Response.End()" inside a finally block.
Move "Response.End()" outside of the try-catch scope.
None of the above solutions have solved the issue. Any further advice on how to resolve this error is greatly appreciate it.
Thanks.
You are causing the exception by calling Response.End. End's documented behavior is to flush buffers and abort the current request immediately by aborting it. It's not used in .NET programming. It's there only for compatibility with old ASP code.
Just remove Response.End() from your code
You should also remove the catch statement. Exceptions should be investigated and fixed, not covered up. An OutOfMemoryException means that there is something seriously wrong with the code that's causing leaks. It can be caused either because you run out of memory or because memory is so fragmented that .NET is unable to allocate a large enough block

Downloading a file, can you cancel the response when an error occurs, without buffering the content

I am writing large CSV files to the Response with Response.BufferOutput set to false. This is because the file has the potential to take a long time to download so the user can see some progress. I generate a line for the CSV from a object and write to the response using Response.Write().
This works well however if there is an unexpected error after the Response has started writing then the client will receive a file with only part of the data and could be missing lots of lines but they might not realise it.
Is there a way to somehow cancel the file download without buffering all the content? Could there be some way to indicate that the response is invalid so the browser disregards the file?
Code below shows the main idea of my code
public void StreamCsvFile(string fileName,List<myObject> myObjectList)
{
Response.Clear();
Response.ContentType = "text/csv";
Response.AddHeader("content-disposition", "filename=" + fileName);
Response.BufferOutput = false;
string headerLine = GetHeaderLine();
Response.Write(headerLine)
try
{
foreach(var myObject in myObjectList)
{
string line = myObject.ToCsvString();
Response.Write("\n" + line);
}
}
finally
{
Response.End();
}
}
Write to a temporary file first.
Set the content-length on the response.
Use Response.TransmitFile to send this temp file.
Browsers will reject download if content length doesn't match.

Detecting if the server still has an ajax request using different browser c# jquery

I'm currently developing a website and having trouble finding the right solution.
When I open my site from a different browser and tried to make an AJAX call at the same time, I get an error, because both the browsers are processing the request.
Is there a way to detect if the server is currently executing an AJAX call and wait until it finishes the first request before executing the second one?
here is my code when i tried to make an ajax request at the same time using different browsers
using (StreamWriter sw = new StreamWriter(hhpPath + "\\Contents\\" + Path.GetFileName(hhpPath).ToString() + ".hhp", false))
{
sw.WriteLine("[OPTIONS]");
sw.WriteLine("Compatibility=1.1 or later");
sw.WriteLine("Compiled file=" + hhpPath + "\\Unpublished\\"+ Name +".chm"); //the file to be converted
sw.WriteLine("Contents file=" + (hhpPath + "\\Contents\\" + Path.GetFileName(hhpPath).ToString()) + ".hhc"); //TOC file
sw.WriteLine("Default topic=" + "Installing the Prototype Terminal.html");
sw.WriteLine("Display compile progress=no");
sw.WriteLine("Index file=" + (hhpPath + "\\Contents\\" + Path.GetFileName(hhpPath).ToString()) + ".hhk"); //index file
sw.WriteLine("Title=none");
sw.WriteLine("\r\n[FILES]");
sw.WriteLine("none");
}
the error says that the file is currently on use.
The fact that it is an AJAX call via jQuery is irrelevant. You problem is: your website tries to exclusively access a resource (in your case, write to a constant file) on a request.
Since the website is designed to simultaneously serve a lot of clients, you will inevitably run into access issues.
The functionality you're trying to achieve isn't really typical for a website. Could you please describe what problem you are trying to solve, so that we could give you a better advise?
Possible solutions could be a combination of:
Write to a different file on each request
(as suggested in another answer) Gracefully handle the file access error: either wait until it's free, or return an error
Use a database instead of the file system for writing data
Limit this feature to specific clients
Remove this feature altogether
You need to lock the file while writing content in file as like below
lock (lockObject)
{
var sw = new StreamWriter(fs);
sw.Write('text');
sw.Flush();
sw.Close();
}
Please check this link for thread synchronization.
When you make ajax request its not directly possible to detect on client side if file is in use . You can put a try catch around that item and return a -1(file locked) status 1(success) or 0(some other error).
Or try following function to check before your code to see if file is in use and return related status to ajax calls.
protected virtual bool IsFileLocked(FileInfo file)
{
FileStream stream = null;
Boolean status = false;
try
{
stream = file.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.None);
status = false ;
}
catch (IOException)
{
//the file is unavailable because it is:
//still being written to
//or being processed by another thread
//or does not exist (has already been processed)
status = true;
}
finally
{
if (stream != null)
stream.Close();
}
//file is not locked
return status;
}

Redirecting a page after a PDF download

I have an aspx (say 1.aspx) page from where first I am downloading a pdf file and then I want to redirect to some Thanks.aspx page. The code is this:
protected void btnSubmit_Click(object sender, EventArgs e)
{
string pathId = string.Empty;
if (Page.IsValid)
{
try
{
pathId = hidId.Value;
DownloadPDF(pathId);
Response.Redirect("Thanks.aspx");
}
catch (Exception ex)
{
throw ex;
}
}
}
protected void DownloadPDF(string pathId)
{
if (!(string.IsNullOrEmpty(pathId)))
{
try
{
Response.ContentType = "application/pdf";
Response.AppendHeader("Content-Disposition", "attachment; filename=" + pathId + ".pdf");
string path = ConfigurationManager.AppSettings["Pdf_Path"].ToString() + "\\" + pathId.Trim() + ".pdf";
Response.TransmitFile(path);
}
catch (Exception ex)
{
throw ex;
}
finally
{
HttpContext.Current.ApplicationInstance.CompleteRequest();
}
}
}
The problem is that, the file save dialog is coming properly and I am able to download the file also, but it is not getting redirected to the Thanks.aspx page.
How to resolve this?
If the file is just downloaded, no preprocessing is done, you could try the following:
Response.AddHeader("Refresh", "12;URL=nextpage.aspx");
Where the number is the seconds before refresh is done :)
I've found it easier to put the PDF download page in an iframe. That way you can activate the PDF download on the client side by just pointing the iframe source to the PDF download page. After that you can either move to a new page, or just show the thank you text right that on the page that has the iframe in it.
In HTTP, a request can only have a single response. Since the first response is the PDF file, the seconds response (i.e. the redirect) cannot be implemented.
You can try to redesign the two pages by redirecting to thanks.aspx and have thanks.aspx start the download automatically.
A Response.Redirect actually sends a response to the browser that basically says this resource has moved to some other URL. However, you're trying to send a file down in a response too, so those two things are probably clashing with each other. Try sending back a little JavaScript that sends them to the page you want to send them too instead of using a Response.Redirect.
ScriptManager.RegisterStartupScript(Me, Me.GetType(), "redirectScript", "window.location.href='whateverurlhere.aspx';", True)
See the article mentioned in this accepted answer: https://stackoverflow.com/a/11018277/1037864
(direct link: http://gruffcode.com/2010/10/28/detecting-the-file-download-dialog-in-the-browser/)
The idea is to set a cookie and send it together with the file. Meanwhile you let the waiting page block the UI while it is waiting for the cookie to arrive.
I tried many things (like the ideas here) but nothing worked for my particular situation. In the end for me I used an approach where my C# sets a cookie that the JavaScript looks for and the form buttons/etc are disabled accordingly until the cookie is detected.
My code is here in case anyone thinks this solution might work for you:
https://gist.github.com/cemerson/9811a384d7f41bc683b2bd9ed4bf5b17

Categories

Resources