Reputation: 206
I am trying to output a CSV file using an endpoint on a service in ServiceStack, using the HttpResult class.
The CSV string itself is being constructed via StringWriter and CsvHelper.
If the content type is set to "text/plain", the text appears on the browser screen fine when the endpoint URL is hit. However, if it is set to "text/csv", a CSV file is generated, but the information inside it is not correct.
For example:
Expected output:
Header 1, Header 2, Header 3
Actual output:
H,e,a,d,e,r, ,1,,, ,H,e,a,d,e,r, ,2,,, ,H,e,a,d,e,r, 3,"
Is there something I'm possibly missing?
Also, on a side note, how do I set the file name for the file itself? It appears I have to use HttpHeaders.ContentDisposition, but when I tried to set it I got an error along the lines of having multiple header elements.
EDIT: Sorry forgot to include code snippet.
string response = string.Empty;
using (var writer = new StringWriter())
{
using (var csv = new CsvWriter(writer))
{
csv.WriteHeader<TestClass>();
foreach (var element in elements)
{
csv.WriteField(elements.header1);
csv.WriteField(elements.header2);
csv.WriteField(elements.header3);
csv.NextRecord();
}
}
//apparently double quotes can cause the rendered CSV to go wrong in some parts, so I added this as part of trying
response = writer.ToString().Replace("\"", "");
}
return new HttpResult(response)
{
StatusCode = HttpStatusCode.OK,
ContentType = "test/csv"
};
And the info on TestClass:
public class TestClass
{
public string Header1 { get; set; }
public string Header2 { get; set; }
public string Header3 { get; set; }
}
Upvotes: 0
Views: 194
Reputation: 143319
From your description your HttpResult
File Response may be serialized by the built-in CSV Format.
If you're not using it you can remove it with:
Plugins.RemoveAll(x => x is CsvFormat);
Otherwise if you are using it, you can circumvent its serialization by writing the CSV file in your Services implementation, e.g:
public class MyCsv : IReturn<string> {}
public async Task Any(MyCsv request)
{
var file = base.VirtualFileSources.GetFile("path/to/my.csv");
if (file == null)
throw HttpError.NotFound("no csv here");
Response.ContentType = MimeTypes.Csv;
Response.AddHeader(HttpHeaders.ContentDisposition,
$"attachment; filename=\"{file.Name}\";");
using (var stream = file.OpenRead())
{
await stream.CopyToAsync(Response.OutputStream);
await Response.OutputStream.FlushAsync();
Response.EndRequest(skipHeaders:true);
}
}
Edit since you're returning a raw CSV string
you can write it to the response with:
Response.ContentType = MimeTypes.Csv;
await Response.WriteAsync(response);
Response.EndRequest(skipHeaders:true);
Upvotes: 1