views:

159

answers:

4

I have a MS SQL view that I want to make available as a CSV download in my ASPNET Web Forms app. I am using Entity Framework for other views and tables in the project. What's the best way to enable this download?

I could add a LinkButton whose click handler iterates over the view, writes its CSV form to the disk, and then serves that file. However, I'd prefer not to write to the disk if it can be avoided, and that involves iteration code that may be avoided with some other solution.

+1  A: 

See this article, specifically the method WriteToCsv(); This will send the csv data to the browser as PersonList.csv.

Update: Possible Asp.Net scenario:

protected void Page_Load(object sender, EventArgs e)
{
  var data = GetMyData(...);
  CSVExporter.WriteToCSV(data);
}
mxmissile
It's a good start, but string values should always be surrounded by quotation marks, as any embedded commas in the data will screw up the CSV otherwise.
Robert Harvey
With this solution, would CSVExporter's methods be merged with a .aspx page that calls WriteToCsv() in its Page_Load()?
ChessWhiz
There's also apparently a Linq to CSV project that supports writing to CSV http://www.codeproject.com/KB/linq/LINQtoCSV.aspx#writing_to_a_file
R0MANARMY
@Chess added a possible asp.net solution, you would not need to merge the code with your aspx file, just create a new class file containing the CSVExporter class.
mxmissile
+1  A: 

You could iterate over the dataset, but instead of creating the CSV file on your server simply return it through the HTTP response. The following function should do the trick.

Public Shared Sub ExportTextFile(ByVal response As System.Web.HttpResponse, ByVal text As String, ByVal fileName As String)

    response.Clear()
    response.AddHeader("content-disposition", String.Format("attachment;filename={0}", fileName))
    response.Charset = ""
    response.Cache.SetCacheability(HttpCacheability.NoCache)
    response.ContentType = "application/vnd.text"

    Dim stringWrite As New System.IO.StringWriter
    Dim htmlWrite = New HtmlTextWriter(stringWrite)
    response.Write(text.ToString)
    response.End()

End Sub
matt
So a method similar to ExportTextFile() would be used as the link's click handler, with no target .aspx page?
ChessWhiz
@Chess you could do that, or drop that code in the Page_Load of a ExportTextFile.aspx page. Then link to that.
mxmissile
If you go this route (and you probably should) consider just implementing your own HTTP Handler so you don't incur the cost of a full page load. See http://www.hanselman.com/blog/PermaLink,guid,5c59d662-b250-4eb2-96e4-f274295bd52e.aspx and http://haacked.com/archive/2005/03/17/AnAbstractBoilerplateHttpHandler.aspx for reference.
R0MANARMY
@ChessWhiz Yes, I'd call ExportTextFile() in a link button click handler.
matt
+1 You should run this in its own HttpHandler, but this is probably the best way to do what you want.
Nate Bross
I went with this route, using an HttpHandler registered in the web.config, and my own custom iteration over the Entity Framework class. Thanks everyone for your help!
ChessWhiz
A: 

Here is my code to ceate a csv file from any IDataReader. Call it using the results of an ExecuteReader() and HttpResponse.OutputStream. It will write out the column names in the first row, then one or more sets of data rows. Output it to the browser as suggested by matt, though I would suggest content type 'text/csv'.

public static void createCsvFile(IDataReader reader, StreamWriter writer) {
  for (int columnCounter = 0; columnCounter < reader.FieldCount; columnCounter++) {
    if (columnCounter > 0) {
      writer.Write(Separator);
    }
    writer.Write(Delimiter + reader.GetName(columnCounter) + Delimiter);
  }
  writer.WriteLine(string.Empty);

  do {
    while (reader.Read()) {
      for (int columnCounter = 0; columnCounter < reader.FieldCount; columnCounter++) {
        if (columnCounter > 0) {
         writer.Write(Separator);
       }
       writer.Write("\""+ reader.GetValue(columnCounter).ToString().Replace('"', '\'') + "\"");
      }
      writer.WriteLine(string.Empty);
    } 
    writer.Flush();
  }
  while (reader.NextResult());
Ray
A: 

I found this question, which addresses the HttpHandler portion of the dilemma.

http://stackoverflow.com/questions/898145/in-asp-net-how-to-get-the-browser-to-download-string-content-into-a-file-c

ChessWhiz