Skip to content

Instantly share code, notes, and snippets.

@atifaziz
Created August 24, 2016 15:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save atifaziz/d5c2e05fb88ba40f4844476bab4aa288 to your computer and use it in GitHub Desktop.
Save atifaziz/d5c2e05fb88ba40f4844476bab4aa288 to your computer and use it in GitHub Desktop.
ASP.NET Web API MediaTypeFormatter for converting a database command into CSV output
#region Copyright (c) 2016 Atif Aziz. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#endregion
using System;
using System.Data.Common;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Formatting;
using System.Net.Http.Headers;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
public sealed class CsvDataFormatter : MediaTypeFormatter
{
public CsvDataFormatter()
{
SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/csv"));
}
public override bool CanReadType(Type type) => false;
public override bool CanWriteType(Type type) => type == typeof(Lazy<DbCommand>);
public override async Task WriteToStreamAsync(Type type, object value, Stream writeStream, HttpContent content,
TransportContext transportContext, CancellationToken cancellationToken)
{
using (var command = ((Lazy<DbCommand>)value).Value)
using (var reader = await command.ExecuteReaderAsync(cancellationToken))
using (var writer = new StreamWriter(writeStream, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false)))
{
var ordinals = Enumerable.Range(0, reader.FieldCount).ToArray();
var headers =
from i in ordinals
// ReSharper disable once AccessToDisposedClosure
select Encode(reader.GetName(i));
await writer.WriteLineAsync(string.Join(",", headers));
while (await reader.ReadAsync(cancellationToken))
{
var fields =
from i in ordinals
// ReSharper disable once AccessToDisposedClosure
select reader.IsDBNull(i)
? string.Empty
// ReSharper disable once AccessToDisposedClosure
: Encode(Convert.ToString(reader.GetValue(i), CultureInfo.InvariantCulture));
await writer.WriteLineAsync(string.Join(",", fields));
}
}
}
static string Encode(string s)
{
const string quote = "\"";
s = s.Replace(quote, quote + quote);
return s.IndexOfAny(QuoteChars) >= 0 ? quote + s + quote : s;
}
static readonly char[] QuoteChars = { ',', '\r', '\n' };
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment