Created
December 22, 2011 03:21
-
-
Save jeffwindsor/1508773 to your computer and use it in GitHub Desktop.
Reflection based MVC Csv File Result for use with lists of models or dtos
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections.Generic; | |
using System.IO; | |
using System.Linq; | |
using System.Reflection; | |
using System.Text; | |
namespace System.Web.Mvc | |
{ | |
/// <summary> | |
/// Reflection Based CSV File Result | |
/// </summary> | |
/// <typeparam name="TSource">source type that will be reflected into rows</typeparam> | |
public class CsvFileResult<TSource> : FileResult | |
{ | |
private const string seperator = ","; | |
private readonly IEnumerable<TSource> _sources; | |
private readonly IEnumerable<string> _limitToPropertyNames; | |
/// <param name="source">source objects for value rows</param> | |
/// <param name="limitToPropertyNames">limit output to these property names</param> | |
public CsvFileResult(IEnumerable<TSource> sources, IEnumerable<string> limitToPropertyNames = null) | |
: base("text/csv") | |
{ | |
_sources = sources; | |
_limitToPropertyNames = limitToPropertyNames; | |
} | |
protected override void WriteFile(System.Web.HttpResponseBase response) | |
{ | |
//Get Reflected objects as a csv table and write it to the response stream | |
using (var stream = new MemoryStream()) | |
{ | |
using (var writer = new StreamWriter(stream, Encoding.Default)) | |
{ | |
writer.Write(ReflectPropertiesToCsvTable(_sources, _limitToPropertyNames)); | |
writer.Flush(); | |
response.OutputStream.Write(stream.GetBuffer(), 0, (int)stream.Length); | |
} | |
} | |
} | |
private static string ReflectPropertiesToCsvTable(IEnumerable<TSource> sources, IEnumerable<string> limitToPropertyNames = null) | |
{ | |
var propertyNames = GetPropertyNames(limitToPropertyNames); | |
var headerValues = ConvertToCsvString(propertyNames); | |
var rowValues = from source in sources select ConvertToCsvString(GetPropertyValues(source, propertyNames)); | |
var sb = new StringBuilder(); | |
sb.AppendLine(headerValues); | |
foreach (var row in rowValues) | |
{ | |
sb.AppendLine(row); | |
} | |
return sb.ToString(); | |
} | |
private static string ConvertToCsvString(IEnumerable<string> source) | |
{ | |
return string.Join(seperator, source); | |
} | |
private static IEnumerable<string> GetPropertyNames(IEnumerable<string> limitToPropertyNames = null) | |
{ | |
return limitToPropertyNames ?? | |
from pi in typeof (TSource).GetProperties() | |
select pi.Name; | |
} | |
public static IEnumerable<string> GetPropertyValues(TSource source, IEnumerable<string> limitToPropertyNames = null) | |
{ | |
//Extract Reflection Info | |
var columns = from pi in source.GetType().GetProperties() | |
orderby pi.Name | |
select new | |
{ | |
pi.Name, | |
Value = GetPropertyValue(pi, source) | |
}; | |
//Filter by Property Names if supplied | |
if (limitToPropertyNames != null) | |
{ | |
columns = from item in columns | |
from allowedName in limitToPropertyNames | |
where item.Name == allowedName | |
select item; | |
} | |
return from item in columns select item.Value; | |
} | |
private static string GetPropertyValue(PropertyInfo pi, object source) | |
{ | |
try | |
{ | |
var result = pi.GetValue(source, null); | |
return (result==null) ? "Null": result.ToString(); | |
} | |
catch (Exception) | |
{ | |
return "Reflection Failed to Obtain Value"; | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment