In C# I'm having trouble with printing out the csv file
As of right now it is just throwing an error, it won't print the file
The error is:
Sys.WebForms.PageRequestManagerParserErrorException: The message received from the server could not be parsed.
Here is my code behind, thanks for any help, I think I'm doing it right though
protected void csvbutton_Click(object sender, EventArgs e)
{
string filename = App_Name_L.ToString();
StringBuilder sb = new StringBuilder();
string[] columnNames = new string[]
{
"APPLICATION NAME",
"DESCRIPTION",
"APPLICATION OWNER",
"TSO",
"RESPONSIBLE MANAGER",
"SIGN OFF",
"CO-EXISTENCE STATUS",
"CO-EXISTENCE PROGRESS",
"MIGRATION PHASE",
"NEXT STEPS",
"LAST UPDATE"
};
sb.AppendLine(string.Join(",", columnNames));
sb.AppendLine(Environment.NewLine);
string[] fields = new string[]
{
App_Name_L.Text.ToString(),
Description_L.Text.ToString(),
App_Owner_L.Text.ToString().Replace(",", "."),
TSO_L.Text.ToString().Replace(",", "."),
Responsible_Manager_L.Text.ToString().Replace(",", "."),
Sign_Off_L.Text.ToString().Replace(",", "."),
this.status_export(0, Convert.ToInt16(CS_H.Value.ToString())),
this.status_export(1, Convert.ToInt16(CP_H.Value.ToString())),
Migration_Phase_L.Text.ToString(),
Next_Steps_L.Text.ToString().Replace(",", "."),
Last_Update_L.Text.ToString()
};
sb.AppendLine(string.Join(",", fields));
stringout.Text = sb.ToString();
Response.Clear();
Response.ContentType = "text/csv";
Response.AddHeader("Content-Disposition", "attachment; filename=\"" + filename + ".csv\"");
Response.Write(sb.ToString());
Response.End();
}
Joel this is something that I have just tested and it works in my environment look at this and see if you can apply it to your code as well replace where I have data with your sb.Tostring();
private static void ExportToExcel(string data)
{
HttpContext.Current.Response.Clear();
HttpContext.Current.Response.AddHeader("content-disposition", "attachment;filename=\"" + filename + ".csv\"");
HttpContext.Current.Response.ContentEncoding = System.Text.Encoding.GetEncoding("UTF-8");
HttpContext.Current.Response.ContentType = "text/csv";
HttpContext.Current.Response.Write(data);
HttpContext.Current.Response.End();
}
Related
Within my code I have an asp repeater and I wish to allow users to export the data from this to a csv file. Exporting to a csv works fine but when I wish to show a dialog box for users to choose where to save to nothing happens. I have went through several different solutions that apparently work but when I run them in my code nothing happens and I can not figure out why. This is my code at the moment:
protected void exportCSV_Click(object sender, EventArgs e)
{
try
{
string FilePath = Server.MapPath("~") + "\\test.csv";
StringBuilder columnbind = new StringBuilder();
foreach (Control item in rpt_bookings.Items)
{
Literal row1 = (Literal)item.FindControl("ltl_bookingemail");
Literal row2 = (Literal)item.FindControl("ltl_bookingphone");
Literal row3 = (Literal)item.FindControl("ltl_bookingcost");
string fullRow = row1.Text.ToString() + "," + row2.Text.ToString() + "," + row3.Text.ToString();
columnbind.Append(fullRow);
columnbind.Append("\r\n");
}
//// Creates the file on server
File.WriteAllText(FilePath, columnbind.ToString());
string FileName = "test.csv";
System.Web.HttpResponse response = System.Web.HttpContext.Current.Response;
response.ClearContent();
response.Clear();
response.ContentType = "text/csv";
response.AddHeader("Content-Disposition", "attachment; filename=" + FileName + ";");
response.TransmitFile(FilePath);
response.Flush();
response.End();
//// Deletes the file on server
File.Delete(FilePath);
//response.End();
lblmsg.Text = "";
}
catch (Exception ex)
{
Console.Write(ex);
Debug.Write(ex);
lblmsg.Text = ex.Message;
lblmsg.Style.Add("color", "#c73939");
}
}
The csv is correctly created but nothing happens with the response. The code executes but nothing comes up on the screen at all. According to several other questions along the same lines this is the solution.
Try the following changes:
response.ContentType = "application/octet-stream";
response.AppendHeader("Content-Disposition","attachment; filename=" + Filename + ";");
response.TransmitFile( FilePath );
response.End();
Don't delete the file in the next line but in the finally block instead:
catch (Exception ex)
{
[..]
}
finally
{
File.Delete(FilePath);
}
I am exporting a csv file with the following code from a datatable. however names with accents are not exported correctly
http://screencast.com/t/i9N2mB34DL
var dt=JobContext.GetEngagementLetterReport(SPContext.Current.Site, int.Parse(rdlOption.SelectedValue));
var columnNames = new List<string>
{
Constants.SearchFields.Client.ClientCode,
Constants.SearchFields.Client.ClientName,
Constants.SearchFields.Job.JobCode,
Constants.SearchFields.Job.JobName,
Constants.SearchFields.Job.JobPartner,
Constants.SearchFields.Job.JobDirector,
Constants.SearchFields.Job.JobManager,
Constants.SearchFields.Job.BillContact,
Constants.SearchFields.Job.LineOfService,
Constants.SearchFields.Job.BusinessUnit,
Constants.SearchFields.Job.OperatingUnit,
"JobSiteUrl",
"FileNameUrl"
};
ExcelHelper.ExportDatatabletoExcel(dt, columnNames);
public static void ExportDatatabletoExcel(DataTable dt, List<string> columnNames)
{
try
{
const string attachment = "attachment; filename=elreport.csv";
HttpContext.Current.Response.ClearContent();
HttpContext.Current.Response.AddHeader("content-disposition", attachment);
HttpContext.Current.Response.ContentType = "application/vnd.ms-excel";
string tab = "";
foreach (DataColumn dc in dt.Columns)
{
if (!columnNames.Contains(dc.ColumnName)) continue;
HttpContext.Current.Response.Write(tab + dc.ColumnName);
tab = ";";
}
HttpContext.Current.Response.Write("\n");
int i;
foreach (DataRow dr in dt.Rows)
{
tab = "";
for (i = 0; i < dt.Columns.Count; i++)
{
if(!columnNames.Contains(dt.Columns[i].ColumnName)) continue;
HttpContext.Current.Response.Write(tab + dr[i].ToString());
tab = ";";
}
HttpContext.Current.Response.Write("\n");
}
HttpContext.Current.Response.End();
}
catch (Exception ex)
{
string errorMessage = String.Format("ExportToExcelError: {0}", ex.Message);
LoggingService.LogError(LoggingCategory.General, ex, errorMessage);
throw;
}
}
Try adding the following after setting the content type.
// This is the missing part from your original code to set the charset and encoding - if this does not work, replace it with appropriate value, eg
Response.Charset = "utf-8";
Response.ContentEncoding = Encoding.UTF8;
// You might want to use this content type or experiment with appropriate MIME type
Response.ContentType = "text/csv";
TQ.
Below shown is my code after creating the CSV file, i want to download the file so i am using below code. but its throwing error " Server cannot append header after HTTP headers have been sent" at "Response.AddHeader("Content-disposition", "attachment; filename=" + fileCSV + "\"");" place. Its downloading but browser not redirecting to same page.
string[] header = { "Error Occurred On", "Controller Name", "Action Name", "Exception Occurred", "Stack Trace Description", "InnerException Occurred", "Stack Trace InnerException Occurred " };
The code:
DataTable dt = new DataTable();
for (int e = 0; e < header.Length; e++)
{
dt.Columns.Add(header[e], typeof(string));
}
StringBuilder sb = new StringBuilder();
IEnumerable<string> columnNames = dt.Columns.Cast<DataColumn>().Select(column => column.ColumnName);
sb.AppendLine(string.Join(",", columnNames));
dt.DefaultView.RowFilter = "[Exception Occurred] LIKE '%" + keyword + "%'";
DataTable dtFilter = new DataTable();
dtFilter = dt.DefaultView.ToTable();
foreach (DataRow row in dtFilter.Rows)
{
IEnumerable<string> fields = row.ItemArray.Select(field => field.ToString());
sb.AppendLine(string.Join(",", fields));
}
System.IO.File.WriteAllText(fileCSV, sb.ToString());
byte[] bytes = Encoding.ASCII.GetBytes(sb.ToString());
if (bytes != null)
{
Response.Clear();
Response.ContentType = "text/csv";
//Response.AddHeader("Content-Length", bytes.Length.ToString());
Response.AddHeader("Content-disposition", "attachment; filename=" + fileCSV);
Response.BinaryWrite(bytes);
Response.Flush();
Response.End();
}
You cannot redirect after downloading the File, you are attempting to perform 2 actions where you can only do the first.
I suggest that you download the file in a new (popup) window and redirect the main page if required.
Edit:-
You could force the download by opening the file-download action using window.open.
Example:-
Download File
<script>
$(function() {
$('a.file-download').click(function() {
window.open($(this).data('file'));
});
});
</script>
In HTTP there is a single response for each request. So this error means that you've already send something to response.
Not sure you are still looking for an answer, but rather than Response.Flush & Response.End, try HttpContext.ApplicationInstance.CompleteRequest(). It has solved a lot of my problems when trying to write directly to request stream.
Some few minutes ago I had the the same problem with a file download. I want to share what worked for me.
The most important thing add:
Response.ClearHeaders();
in the begin of action result.
And, to be honest, I read it here https://www.codeproject.com/Questions/1038819/How-to-resolve-this-error-Server-cannot-append-hea
I got a problem when export an arabic work to excel from c# code behind:
the code I use for :
HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache);
string attachment = "attachment; filename=Employee.xls";
HttpContext.Current.Response.Clear();
HttpContext.Current.Response.Buffer = true;
HttpContext.Current.Response.Charset = "UTF-8";
HttpContext.Current.Response.ContentEncoding = System.Text.Encoding.UTF8;
HttpContext.Current.Response.AddHeader("content-disposition", attachment);
HttpContext.Current.Response.ContentType = "application/vnd.ms-excel";
Response.Write("السبت");// this word mean Saturday in arabic
Response.End();
Application.UnLock();
but after I open the excel file its look like :
why the word look like this and how to fix it ?
and if you see in the second row the size of the word didn't fit with the size of the cell how to do it ?
another question : how to color the background of the cell from c# code behind and how to combine cell ?
thx any way
I took your example rewrote it on my end just now tested it and everything works fine
I wonder if you are experiencing a Culture issue
keep in mind the filename I am assigning on my end and passing it to a Method
public static void ExportToExcel(DataTable table, string fileName)
{
HttpContext context = HttpContext.Current;
context.Response.Clear();
context.Response.ContentEncoding = System.Text.Encoding.GetEncoding("windows-1254");
context.Response.Charset = "windows-1254"; //ISO-8859-13 ISO-8859-9 windows-1254
//Begin Table
context.Response.Write("<table><tr>");
//Write Header
foreach (DataColumn column in table.Columns)
{
context.Response.Write("<th>" + column.ColumnName + "</th>");
}
context.Response.Write("</tr>");
//Write Data
foreach (DataRow row in table.Rows)
{
context.Response.Write("<tr>");
for (int i = 0; i < table.Columns.Count; i++)
{
context.Response.Write("<td>" + row[i].ToString().Replace(",", string.Empty) + "</td>");
}
context.Response.Write("</tr>");
}
//End Table
context.Response.Write("</table>");
context.Response.ContentType = "application/vnd.ms-excel";
context.Response.AppendHeader("content-disposition", string.Format("attachment;filename={0}.xls", fileName));
context.Response.Flush();
context.Response.End();
}
use 1256 rather than 1254 it's working good :)
HttpContext context = HttpContext.Current;
context.Response.Clear();
context.Response.ContentEncoding = System.Text.Encoding.GetEncoding("windows-1256");
context.Response.Charset = "windows-1256"; //ISO-8859-13 ISO-8859-9 windows-1256
Here is my code..
string attachment = "attachment; filename=Call-Details-Report-" + startDate.SelectedDate.Value.ToString("MM-dd-yyyy") + ".csv";
Response.Clear();
Response.ClearHeaders();
Response.ClearContent();
Response.AddHeader("Content-Disposition", attachment);
Response.ContentType = "text/csv";
Response.AddHeader("Pragma", "public");
Response.WriteFile(downloadLocation+"\\"+fileName);
Response.End();
I'm using the above code to download a csv file from a location.But surprisingly the contents gets written twice or some times thrice into the file that i download though actually it isn't so with the file on server.I'm writing my code in c#.
The above piece of code works perfectly in local machine,but the issue is in Production server.
Here is my complete Method
private void DownloadReport(string query)
{
string downloadFolderPath = "";
string filePath = "";
string dbAndApplicationServerStatus = ConfigurationManager.AppSettings["SameDBAndApplicationServer"] != null ? ConfigurationManager.AppSettings["SameDBAndApplicationServer"] : "1";
if (dbAndApplicationServerStatus == "0")
{
Log.Write("So the DB And Application are on differrent servers,hence trying to read Download folder path on DB Server....");
downloadFolderPath = ConfigurationManager.AppSettings["ReportDownloadLocation"] != null ? ConfigurationManager.AppSettings["ReportDownloadLocation"] : "-1";
Log.Write("Download Path is " + downloadFolderPath);
}
else
{
Log.Write("So the DB and Application and Db are on same server......");
downloadFolderPath = Server.MapPath("Download");
downloadFolderPath = downloadFolderPath.Replace("\\", "//");
if (!Directory.Exists(downloadFolderPath))
{
Directory.CreateDirectory(downloadFolderPath);
}
Log.Write("Download Path is " + downloadFolderPath);
}
string status="";
StringBuilder headerQuery = new StringBuilder();
StringBuilder rowQuery = new StringBuilder();
StringBuilder sqlQuery = new StringBuilder();
filePath = downloadFolderPath;
string folderName = DateTime.Now.ToString("MM-dd-yyyy");
string timeStamp = DateTime.Now.ToString("MM-dd-yy-HH-mm-ss");
string fileName = "Call-Details-Report-" + startDate.SelectedDate.Value.ToString("MM-dd-yyyy") + "_" + timeStamp + ".csv";
filePath = filePath + "/" + fileName;
bool commaRequired = false;
sqlQuery.Append("SELECT * INTO OUTFILE '");
sqlQuery.Append(filePath);
sqlQuery.Append("' FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '\"' LINES TERMINATED BY '\n' FROM (");
headerQuery.Append("Select ");
rowQuery.Append("(Select ");
#region Creating Query
/*Sql Query is Created in this region*/
#endregion
if (!CdrSearch.WriteReportToFile(sqlQuery.ToString(),out status))
{
Log.Write("Failed to generate the file to download......");
WebPagesHelper.ShowMessage(ref lblMessage, WebPagesHelper.MessageType.Message, status);
}
else
{
Log.Write("Succesfully generated file to Download");
string downloadLocation = Server.MapPath("Download");
if (dbAndApplicationServerStatus == "0")
{
WebClient webClient = new WebClient();
string path = ConfigurationManager.AppSettings["DownloadURL"] != null ? ConfigurationManager.AppSettings["DownloadURL"].ToString() : "";
if (!Directory.Exists(downloadLocation))
{
Directory.CreateDirectory(downloadLocation);
}
if (File.Exists(downloadLocation + "\\" + fileName))
{
File.Delete(downloadLocation + "\\" + fileName);
}
webClient.DownloadFile(path + fileName, downloadLocation + "\\" + fileName);
}
Log.Write("Configured Download Location on Application" + downloadLocation);
string attachment = "attachment; filename=Call-Details-Report-" + startDate.SelectedDate.Value.ToString("MM-dd-yyyy") + ".csv";
Response.Clear();
Response.ClearHeaders();
Response.ClearContent();
Response.AddHeader("Content-Disposition", attachment);
Response.ContentType = "text/csv";
Response.AddHeader("Pragma", "public");
Log.Write(downloadLocation + "\\" + fileName);
Response.WriteFile(downloadLocation+"\\"+fileName);
Response.SetCookie(new HttpCookie("DStatus", "Completed"));
Response.End();
}
}
And the above method is called only once straight away on click of a button,so no question of any looping here.
You may check what the following lines are meant for :
webClient.DownloadFile(path + fileName, downloadLocation + "\\" + fileName);
Response.WriteFile(downloadLocation+"\\"+fileName);
Give a try by commenting out one of them, if they are really doing the same.
As a safe measure, please disable the button until your download is finished.
When i tried the following code (even published on IIS), it is just downloading once, as expected.
protected void Button1_Click(object sender, EventArgs e)
{
string attachment = "attachment; filename=Call-Details-Report-" + DateTime.Now.ToString("MM-dd-yyyy") + ".txt";
Response.ContentType = "text/html";
Response.AddHeader("Content-Disposition", attachment);
Response.AddHeader("Pragma", "public");
Response.WriteFile(#"C:\test.txt");
Response.SetCookie(new HttpCookie("DStatus", "Completed"));
Response.End();
}
There's obviously something hinky going on. You've said that it works in dev but not Prod - Are you using the same server config in both environemts (ie are you using 1 server in dev but 2 in prod?)
You've potentially got 3 steps, assuming I've understood your code...
Generate Report from SQL and write it to a file
If the file is stored on a different server, download it to the web server
Serve it
So, in the more complex scenario (which I assume Production is), At what step in the process do you start to see double entries? On the server the report is generated on, on the web servers' copy or only in the client after getting it from the Webserver?
I can't see any reason why your code to serve the file to the client would be duplicating data so can only assume it's happening before there at some point.
It would be helpful if you could use Firebug/Fiddler/??? to post the exact contents of the transmission from the webserver to the client
(Incidentally, you may want to look at the System.IO.Path class for manipulating paths, it makes your code more readable and robust - No more worrying about trailing slashes!)
ok so the real culprit was Response.WriteFile in this case.In my case i guess since the size of data was quite huge Response.WriteFile was not working as expected.I found some where that in case of large file downloads, its best to use Response.TransmitFile.Left with no other option i changed my code and used Response.TransmitFile and eureka! the problem was solved.No more duplicate records in downloaded file.Though the reason is still unknown, Response.TransmitFile solved the issue.....