csv file not downloading in chrome browser from asp.net c# app - c#

i m using the following code to send a csv file through http request.The code runs fine but the file is not downloaded on client machine , not save as menu ,nothing appears . The same code i have used for another report and it works fine and file is also downloaded . I m running the project on local host. but not for the button btnGenerateReport.
protected void btnGenerateReport_Click(object sender, EventArgs e)
{
DataTable dt = new DataTable();
MHSProgressNotesBL oMHSProgressNote = new MHSProgressNotesBL();
int ClientId = Convert.ToInt32(ddlClients.SelectedValue);
int LocationId = Convert.ToInt32(ddlLocations.SelectedValue);
int PractitionerId = Convert.ToInt32(ddlPractitioner.SelectedValue);
dt = oMHSProgressNote.FetchBillingReport(LocationId, ClientId, PractitionerId, Convert.ToDateTime(txtNoteStartDate.Text), Convert.ToDateTime(txtNoteEndDate.Text));
WriteToCSV(dt);
}
private void WriteToCSV(DataTable dt)
{
try
{
string attachment = "attachment; filename=ClientRoster.csv";
HttpContext.Current.Response.Clear();
HttpContext.Current.Response.ClearHeaders();
HttpContext.Current.Response.ClearContent();
HttpContext.Current.Response.AddHeader("content-disposition", attachment);
HttpContext.Current.Response.ContentType = "text/csv";
//HttpContext.Current.Response.AddHeader("Pragma", "public");
WriteColumnName(dt);
foreach (DataRow clientdata in dt.Rows)
{
WriteUserInfo(clientdata);
}
HttpContext.Current.Response.End();
//HttpContext.Current.ApplicationInstance.CompleteRequest();
}
catch (Exception e)
{ }
}
private void WriteColumnName(DataTable dt)
{
string columnNames = "";
// Write Header row
foreach (DataColumn item in dt.Columns)
{
if (item.ColumnName.Contains(','))
{
columnNames += "\"" + item.ColumnName + "\"";
}
else
{
columnNames += item.ColumnName + ",";
}
}
columnNames = columnNames.TrimEnd(',');
HttpContext.Current.Response.Write(columnNames);
HttpContext.Current.Response.Write(Environment.NewLine);
}
private void WriteUserInfo(DataRow clientDataRow)
{
StringBuilder stringBuilder = new StringBuilder();
foreach (var item in clientDataRow.ItemArray)
{
AddComma((string)(item == System.DBNull.Value ? "" : item.ToString()), stringBuilder);
}
HttpContext.Current.Response.Write(stringBuilder.ToString().TrimEnd(','));
HttpContext.Current.Response.Write(Environment.NewLine);
}
private void AddComma(string value, StringBuilder stringBuilder)
{
if (value.Contains('"'))
{
value = value.Replace(#"""", #"""""");
value = "\"" + value + "\"";
}
else if (value.Contains(','))
{
value = "\"" + value + "\"";
}
stringBuilder.Append(value);
stringBuilder.Append(",");
}

The code is ok ......... the main problem was the button btnGenerateReport was inside of a update panel .Due to which an error was rising :The message received from the server could not be parsed. Common causes for this error are when the response is modified by calls to Response.Write(), response filters, HttpModules, or server trace is enabled.
Details: Error parsing near 'Client,Practitioner,'.
The code worked fine after placing the button outside of update panel.

Related

CSV File showing HTML page source

I am exporting a CSV file from an ASP .NET page but somehow it contains HTML code and the data that are supposed to be exported (ie. 29 rows) are not complete (ie from supposedly 29 rows, only 17 shows up, and then HTML all the way down).
Here are my codes:
private void WriteToCSV()
{
var clientId = int.Parse(ddlClients.SelectedValue);
var taskTypeId = int.Parse(ddlTaskType.SelectedValue);
var mtComponent = new MainTableComponent();
var data = mtComponent.GetMainTableRecords(clientId, 0, taskTypeId);
if (data == null || data.Count == 0)
{
ShowAlertMessage("No available data to export.");
return;
}
var callerId = GetClientList().FirstOrDefault(x => x.ClientId == clientId).CallerId;
string attachment = string.Concat("attachment; filename=CallList_", ddlClients.SelectedItem.Text,
"_", ddlTaskType.SelectedItem.Text, "_", DateTime.Now.ToString("yyyyMMdd"), ".csv");
HttpContext.Current.Response.Clear();
HttpContext.Current.Response.ClearHeaders();
HttpContext.Current.Response.ClearContent();
HttpContext.Current.Response.AddHeader("content-disposition", attachment);
HttpContext.Current.Response.ContentType = "text/csv";
HttpContext.Current.Response.AddHeader("Pragma", "public");
HttpContext.Current.Response.Write("row,phone1,phone2,phone3,caller_id");
foreach (var d in data)
WriteUserInfo(d, callerId);
HttpContext.Current.Response.End();
}
private void WriteUserInfo(MainTableEntity person, string callerId)
{
HttpContext.Current.Response.Write(Environment.NewLine);
StringBuilder stringBuilder = new StringBuilder();
AddComma(person.RowNumber.ToString(), stringBuilder);
AddComma(FormatNumber(person.MobileNumber), stringBuilder);
AddComma("", stringBuilder);
AddComma("", stringBuilder);
AddComma(callerId, stringBuilder);
stringBuilder.Remove(stringBuilder.Length - 1, 1);
HttpContext.Current.Response.Write(stringBuilder.ToString());
}
private void AddComma(string value, StringBuilder stringBuilder)
{
value.Replace(",", "");
stringBuilder.Append(value).Append(",");
}
private string FormatNumber(string number)
{
if (string.IsNullOrWhiteSpace(number))
return null;
string n = number.Replace('-', ' ').Replace(" ", "").Trim();
return n;
}
The funny thing is, this does not happen on my local machine and on our test environment. It only happens in our production environment.
Any help is appreciated. Thank you very much!

Export to Excel, names with accent are not exported correctlty

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.

writing a logfile when backgroundWorker job completed

I have c# application where it displays a message on messagebox after the query is run.At the sametime I want it to write a logfile. This is what i tried but no luck. My logfile was empty.
It had created a empty file.
private void backgroundWorker_Import_DoWork(object sender, DoWorkEventArgs e)
{
//Finally, loop through each row in the dataView and execute INSERT Statements against database
int recCount = 0;
successCount = 0;
failedCount = 0;
dv.RowFilter = "execute_bit IN ('1')";
using (MySqlConnection connectionMySql = new MySqlConnection(connectionStringMySql))
{
connectionMySql.Open();
MySqlCommand commandMySql = new MySqlCommand();
commandMySql.Connection = connectionMySql;
foreach (DataRowView rowView in dv)
{
recCount++;
backgroundWorker_Import.ReportProgress(recCount);
commandMySql.CommandText = rowView["sql"].ToString();
try
{
successCount = successCount + commandMySql.ExecuteNonQuery();
//WriteToLogFile("");
//WriteToLogFile("");
**WriteToLogFile(DateTime.Now.ToString() + ", " + recCount.ToString() + "," + successCount.ToString() + "," + failedCount.ToString());
}**
catch (Exception)
{
failedCount++;
}
}
}
}
private void backgroundWorker_Import_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
string msg = "";
msg = msg + "Records successfully imported: " + successCount.ToString() + Environment.NewLine;
msg = msg + "Records that failed to import: " + failedCount.ToString() + Environment.NewLine + Environment.NewLine;
msg = msg + "Records excluded from import (20 minute grace-period): " + (tblVehicles.Rows.Count - successCount - failedCount).ToString();
progressBar1.Visible = false;
MessageBox.Show( msg, "Operation complete", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
**private void WriteToLogFile(string[] output)
{
StreamWriter sw = null;
FileStream fs = null;
string logfileFileName = System.IO.Path.Combine( "C:/luvi/logfile.txt");
fs = File.Open(logfileFileName, FileMode.Append, FileAccess.Write);
sw = new StreamWriter(fs, System.Text.Encoding.UTF8);
foreach (string line in output)
{
sw.WriteLine(line);
}
sw.Close();
sw = null;
}**
You could use File.WriteAllLines as shown in this topic.
Its' syntax is as follows:
public static void WriteAllLines(
string path,
string[] contents
)
In your case you would use it like so:
string logfileFileName = #"C:/luvi/logfile.txt";
File.WriteAllLines(logfileFileName, output);
Note: this overwrites the file, if you want to append them use File.AppendAllLines.
You need to actually call your method aswell, which may be a problem because I do not see that in your code. In the following changes I have replaced the string msg for an array, and added those (you could also use a list and call list.Add).
private void backgroundWorker_Import_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
string[] msg = new string[] {};
msg[0] = "Records successfully imported: " + successCount.ToString();
msg[1] = "Records that failed to import: " + failedCount.ToString();
msg[2] = "Records excluded from import (20 minute grace-period): " + (tblVehicles.Rows.Count - successCount - failedCount).ToString();
// Write to log!
WriteToLogFile(msg);
// Show to messagebox.
string showmsg = msg[0] + Environment.NewLine + msg[1] + Environment.NewLine + msg[2];
progressBar1.Visible = false;
MessageBox.Show(showmsg, "Operation complete", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
private void WriteToLogFile(string[] output)
{
string logfileFileName = "C:/luvi/logfile.txt";
File.AppendAllLines(logfileFileName, output);
}
it seem problem with WriteToLogFile( string[] output) method. You are passing single string while it is expecting arrary of string. catch block is failing it silently.

sqlBulk insert C#

I have a page where I want to upload a CSV file from my computer to database on the server and I have my opentext that looks like the following
using (StreamReader sr = File.OpenText(#"c:\users\workstationUsername\FileName.csv"))
This works fine on my local machine but when I push this to the server it tries to read the server's C Drive and I want it to read the physical file location that is sitting on the desktop of the user's computer not the server, when they click browse and upload..
Thank you
below is the complete code:
if (IsPostBack)
{
// SetDefaultDates();
Boolean fileOK = false;
String dateString = DateTime.Now.ToString("MMddyyyy");
String UserName = User.Identity.Name;
String path = Server.MapPath("~/Uploads/CSVs/");
string stringpath = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
String fileName = System.IO.Path.GetFileName(FileUpload1.PostedFile.FileName);
stringpath = stringpath + fileName;
String LocationToSave = path + "\\" + fileName;
if (FileUpload1.HasFile)
{
String fileExtension =
System.IO.Path.GetExtension(FileUpload1.FileName).ToLower();
String[] allowedExtensions = { ".csv" };
for (int i = 0; i < allowedExtensions.Length; i++)
{
if (fileExtension == allowedExtensions[i])
{
fileOK = true;
}
}
}
if (fileOK)
{
try
{
//FileUpload1.PostedFile.SaveAs(LocationToSave + dateString + "-" + FileUpload1.FileName);
FileUpload1.PostedFile.SaveAs(LocationToSave);
Label1.Text = "File " + FileUpload1.FileName + " uploaded!";
DataTable dt = new DataTable();
string line = null;
int i = 0;
using (StreamReader sr = File.OpenText(stringpath))
{
while ((line = sr.ReadLine()) != null)
{
string[] data = line.Split(',');
if (data.Length > 0)
{
if (i == 0)
{
foreach (var item in data)
{
dt.Columns.Add(new DataColumn());
}
i++;
}
DataRow row = dt.NewRow();
row.ItemArray = data;
dt.Rows.Add(row);
}
}
}
using (SqlConnection cn = new SqlConnection(ConfigurationManager.ConnectionStrings["Myconnection"].ConnectionString))
{
cn.Open();
using (SqlBulkCopy copy = new SqlBulkCopy(cn))
{
copy.WriteToServer(dt);
}
}
}
catch (Exception ex)
{
Label1.Text = "File " + FileUpload1.FileName + " could not be uploaded." + ex.Message;
}
}
else
{
Label1.Text = "Cannot accept files of this type. " + FileUpload1.FileName;
}
}
SetDefaultDates();
}
If you have a FileUpload control, then instead of using (StreamReader sr = File.OpenText(#"c:\users\workstationUsername\FileName.csv")) which obvously is pointing to the server's hard drive you can do this:
(StreamReader sr = new StreamReader(fileUploadControl.FileContent))
//Do your stuff
You can't access the client's hard drive. That's a major security concern. You'll need to upload the file to your server, and read it from there.
It doesnt make sense to have a static read to the local machine, rather get user to upload it then update the database, this code is very limiting and has a high security risk. Rather create a steamreader object get the user to upload it then use the steam reader to process the csv.

Exporting a Custom Excel File with RadGrid

I can export my radgrid to an excel file but I want to add some more info into the sheet.
If it is possible, I would appreciate for a tutorial/sample code for doing a custom excel file generation.
<tel:radgrid runat="server" id="mygrid" skinid="RadGrid_Search_Standard">
<ExportSettings HideStructureColumns="true" />
</tel:radgrid>
Grid is databound with some datatable and I need to add some data
to add some strings above
mygrid.MasterTableView.ExportToWord()
Here's some code that I use with a Telerik Grid, rather than using the ExportToExcel function they've provided I created my own button that fires it's own export event.
I have a function (not included) called getDataSource that I use to populate the grid, you could override this or create your own to fetch the data into a DataTable and add any rows/columns/data as you see fit.
//export button calls this
private void ExportReport()
{
SetPublicVariables();
System.Data.DataTable dt = GetDataSource(false);
string exportData = buildCSVExportString(dt);
string filename = string.Format("{0} - {1}.csv",
(Master as MasterPages.Drilldown).Titlelbl.Text, CampaignTitle);
if (filename.Length > 255) filename = filename.Substring(0, 255);
ExportCSV(exportData, filename);
}
//build a string CSV
public static string buildCSVExportString(DataTable exportDT)
{
StringBuilder exportData = new StringBuilder();
// get headers.
int iColCount = exportDT.Columns.Count;
for (int i = 0; i < iColCount; i++)
{
exportData.Append(exportDT.Columns[i].ToString());
if (i < iColCount - 1)
{
exportData.Append(",");
}
}
exportData.Append(System.Environment.NewLine);
// get rows.
foreach (DataRow dr in exportDT.Rows)
{
for (int i = 0; i < iColCount; i++)
{
if (!Convert.IsDBNull(dr[i]))
{
//If the variable is a string it potentially has charaters that can't be parsed properly.
//this fixes the comma issue(which adds aditional columns). Replace and escape " with "".
if (dr[i] is string)
exportData.Append(String.Format(#"""{0}""", ((string)dr[i]).Replace("\"", #"""""")));
else
exportData.Append(dr[i].ToString());
}
if (i < iColCount - 1)
{
exportData.Append(",");
}
}
exportData.Append(System.Environment.NewLine);
}
return exportData.ToString();
}
public void ExportCSV(string content, string filename)
{
filename = RemoveIllegalPathChars(filename);
HttpResponse Response = HttpContext.Current.Response;
string ext = System.IO.Path.GetExtension(filename);
Response.ClearHeaders();
Response.AddHeader("Content-Disposition", string.Format("attachment;filename=\"{0}\"", filename));
Response.ContentType = "text/csv; charset-UTF-8;";
Response.Clear();
Response.Write(content);
Response.End();
}
A possible way would be to modify the HTML code just before exporting. Here is how.
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
RadGridName.GridExporting += (s, a) =>
{
string myHtmlCode = "<span>My HTML code goes here</span>";
a.ExportOutput = a.ExportOutput.Replace("<body>", "<body>" + myHtmlCode);
};
}
This should work for both Excel (not ExcelML) and Word.
Good luck
The only thing you need to do is add your additional page info to the ExportOutput of your arg
void yourRadGridID_GridExporting(object sender, GridExportingArgs e)
{
string additionalPageInfo= "your html code for the additional page info goes here";
e.ExportOutput = e.ExportOutput.Replace("`<body>`", "`<body>`" + additionalPageInfo);
}

Categories

Resources