public override void SetDefaultContentHeaders(Type type, HttpContentHeaders headers, MediaTypeHeaderValue mediaType) { // Get the raw request URI. string rawUri = System.Web.HttpContext.Current.Request.RawUrl; // Remove query string if present. int queryStringIndex = rawUri.IndexOf('?'); if (queryStringIndex > -1) { rawUri = rawUri.Substring(0, queryStringIndex); } string fileName; // Look for ExcelDocumentAttribute on class. var itemType = FormatterUtils.GetEnumerableItemType(type); var excelDocumentAttribute = FormatterUtils.GetAttribute <ExcelDocumentAttribute>(itemType ?? type); if (excelDocumentAttribute != null && !string.IsNullOrEmpty(excelDocumentAttribute.FileName)) { // If attribute exists with file name defined, use that. fileName = excelDocumentAttribute.FileName; } else { // Otherwise, use either the URL file name component or just "data". fileName = System.Web.VirtualPathUtility.GetFileName(rawUri) ?? "data"; } // Add XLSX extension if not present. if (!fileName.EndsWith("xlsx", StringComparison.CurrentCultureIgnoreCase)) { fileName += ".xlsx"; } // Set content disposition to use this file name. headers.ContentDisposition = new ContentDispositionHeaderValue("inline") { FileName = fileName }; base.SetDefaultContentHeaders(type, headers, mediaType); }
public override Task WriteToStreamAsync(Type type, object value, System.IO.Stream writeStream, System.Net.Http.HttpContent content, System.Net.TransportContext transportContext) { // Create a worksheet var package = new ExcelPackage(); package.Workbook.Worksheets.Add("Data"); var worksheet = package.Workbook.Worksheets[1]; int rowCount = 0; var valueType = value.GetType(); // Apply cell styles. if (CellStyle != null) { CellStyle(worksheet.Cells.Style); } // Get the item type. var itemType = (FormatterUtils.IsSimpleType(valueType)) ? null : FormatterUtils.GetEnumerableItemType(valueType); // If a single object was passed, treat it like a list with one value. if (itemType == null) { itemType = valueType; value = new object[] { value }; } // Enumerations of primitive types are also handled separately, since they have // no properties to serialise (and thus, no headers or attributes to consider). if (FormatterUtils.IsSimpleType(itemType)) { // Can't convert IEnumerable<primitive> to IEnumerable<object> var values = (IEnumerable)value; foreach (var val in values) { AppendRow(new object[] { val }, worksheet, ref rowCount); } // Autofit cells if specified. if (AutoFit) { worksheet.Cells[worksheet.Dimension.Address].AutoFitColumns(); } // Save and done. return(Task.Factory.StartNew(() => package.SaveAs(writeStream))); } var data = value as IEnumerable <object>; // What remains is an enumeration of object types. var serialisableMembers = FormatterUtils.GetMemberNames(itemType); var metadata = ModelMetadataProviders.Current.GetMetadataForType(null, itemType); var properties = (from p in itemType.GetProperties() where p.CanRead & p.GetGetMethod().IsPublic & p.GetGetMethod().GetParameters().Length == 0 select p).ToList(); var fields = new List <string>(); var fieldInfo = new ExcelFieldInfoCollection(); // Instantiate field names and fieldInfo lists with serialisable members. foreach (var field in serialisableMembers) { var propName = field; var prop = properties.FirstOrDefault(p => p.Name == propName); if (prop == null) { continue; } fields.Add(field); fieldInfo.Add(new ExcelFieldInfo(field, FormatterUtils.GetAttribute <ExcelColumnAttribute>(prop))); } if (metadata != null && metadata.Properties != null) { foreach (var modelProp in metadata.Properties) { var propertyName = modelProp.PropertyName; if (!fieldInfo.Contains(propertyName)) { continue; } var field = fieldInfo[propertyName]; var attribute = field.ExcelAttribute; if (!field.IsExcelHeaderDefined) { field.Header = modelProp.DisplayName ?? propertyName; } if (attribute != null && attribute.UseDisplayFormatString) { field.FormatString = modelProp.DisplayFormatString; } } } if (fields.Count == 0) { return(Task.Factory.StartNew(() => package.SaveAs(writeStream))); } // Add header row AppendRow((from f in fieldInfo select f.Header).ToList(), worksheet, ref rowCount); // Output each row of data if (data != null && data.FirstOrDefault() != null) { foreach (var dataObject in data) { var row = new List <object>(); for (int i = 0; i <= fields.Count - 1; i++) { var cellValue = GetFieldOrPropertyValue(dataObject, fields[i]); var info = fieldInfo[i]; // Boolean transformations. if (info.ExcelAttribute != null && info.ExcelAttribute.TrueValue != null && cellValue.Equals("True")) { row.Add(info.ExcelAttribute.TrueValue); } else if (info.ExcelAttribute != null && info.ExcelAttribute.FalseValue != null && cellValue.Equals("False")) { row.Add(info.ExcelAttribute.FalseValue); } else if (!string.IsNullOrWhiteSpace(info.FormatString) & string.IsNullOrEmpty(info.ExcelNumberFormat)) { row.Add(string.Format(info.FormatString, cellValue)); } else { row.Add(cellValue); } } AppendRow(row.ToArray(), worksheet, ref rowCount); } } // Enforce any attributes on columns. for (int i = 1; i <= fields.Count; i++) { if (!string.IsNullOrEmpty(fieldInfo[i - 1].ExcelNumberFormat)) { worksheet.Cells[2, i, rowCount, i].Style.Numberformat.Format = fieldInfo[i - 1].ExcelNumberFormat; } } // Header cell styles if (HeaderStyle != null) { HeaderStyle(worksheet.Row(1).Style); } if (FreezeHeader) { worksheet.View.FreezePanes(2, 1); } var cells = worksheet.Cells[worksheet.Dimension.Address]; // Add autofilter and fit to max column width (if requested). if (AutoFilter) { cells.AutoFilter = AutoFilter; } if (AutoFit) { cells.AutoFitColumns(); } // Set header row where specified. if (HeaderHeight.HasValue) { worksheet.Row(1).Height = HeaderHeight.Value; worksheet.Row(1).CustomHeight = true; } return(Task.Factory.StartNew(() => package.SaveAs(writeStream))); }