Reputation: 867
I am using WebApi2 with angular on my client. I am trying to implement export to excel file in my website. I implemented custom BufferedMediaTypeFormatter. But unfortunately it doesn't work. The WriteToStream function never get called, although the CanWriteType function is get called twice and returning true both times. this is my code:
public class FileMediaFormatter : BufferedMediaTypeFormatter
{
public const string SupportedMediaType = "text/html";
public FileMediaFormatter()
{
SupportedMediaTypes.Add(new MediaTypeHeaderValue(SupportedMediaType));
}
public override bool CanReadType(Type type)
{
return false;
}
public override bool CanWriteType(Type type)
{
if (ExportableResolver.Instance.Value.CanConvert(type))
return true;
if (!type.IsGenericType)
return false;
var arguments = type.GetGenericArguments();
if (arguments.Length != 1)
return false;
var ienumType = typeof(IEnumerable<>).MakeGenericType(arguments[0]);
if (!ienumType.IsAssignableFrom(type))
return false;
return arguments[0].IsClass;
}
public override void WriteToStream(Type type, object value, Stream writeStream, HttpContent content)
{
IEnumerable<object> enumValue;
Type genericType = type;
if (ExportableResolver.Instance.Value.CanConvert(value.GetType()))
{
enumValue = ExportableResolver.Instance.Value.Convert(value);
genericType = enumValue.GetType();
}
else
{
enumValue = (value as IEnumerable<object>);
if (enumValue.Count() > 0)
{
genericType = typeof(List<>).MakeGenericType(enumValue.First().GetType());
}
else
{
// source of baseentity is no important because its just makes an empty file
genericType = typeof(List<>).MakeGenericType(new FileArchive.Domain.Entities.FileProperties().GetType());
}
var a = genericType.Name;
}
if (enumValue == null)
{
base.WriteToStream(type, value, writeStream, content);
return;
}
var list = enumValue as object[] ?? enumValue.ToArray();
var fTypeObj = HttpUtility.ParseQueryString(HttpContext.Current.Request.RawUrl).Get("fType");
if (fTypeObj != null)
{
string fType = fTypeObj.ToString();
var dataTable = DependencyResolver.Current.GetService<IExportXslService>().ConvertToDataTable(list.ToList(), genericType.GetGenericArguments()[0]);
DependencyResolver.Current.GetService<IExportXslService>().WriteDataTableToStream(dataTable, string.Format("{0}", genericType.GetGenericArguments()[0].Name), writeStream, string.Empty);
}
}
public override void SetDefaultContentHeaders(Type type, HttpContentHeaders headers, MediaTypeHeaderValue mediaType)
{
if (CanWriteType(type))
{
string typeName = ExportableResolver.Instance.Value.CanConvert(type)
? type.Name
: type.GetGenericArguments()[0].Name;
//if object (its for the complex type tbls) then give the assembly name
typeName = typeName == "Object" ? System.Reflection.Assembly.GetExecutingAssembly().GetName().Name : typeName;
//string tempFileName = GetHebrewFileName(typeName);
//if (!string.IsNullOrEmpty(tempFileName))
// typeName = tempFileName;
headers.ContentType = new MediaTypeHeaderValue("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") { FileName = string.Format("{0}_{1:yyyyMMddHHmmss}.xlsx", typeName, DateTime.Now) };
var fTypeObj = HttpUtility.ParseQueryString(HttpContext.Current.Request.RawUrl).Get("fType");
if (fTypeObj != null)
{
string fType = fTypeObj.ToString();
if (fType == "excel")
{
headers.ContentType = new MediaTypeHeaderValue("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") { FileName = string.Format("{0}_{1:yyyyMMddHHmmss}.xlsx", typeName, DateTime.Now) };
}
else if (fType == "text")
{
headers.ContentType = new MediaTypeHeaderValue("text/plain");
headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") { FileName = string.Format("{0}_{1:yyyyMMddHHmmss}.txt", typeName, DateTime.Now) };
}
return;
}
}
base.SetDefaultContentHeaders(type, headers, mediaType);
}
}
on WebApiConifg Register function I added:
config.Formatters.Insert(0,new FileMediaFormatter());
What am I missing please?
Upvotes: 0
Views: 545
Reputation: 101
In case anyone comes across this problem I experienced it and my issue was that while my formatter was able to respond 'true' to CanWriteType(myCustomType) it did not cope when the final game was played out.
The final 'lets do it' invokation was based on 'ObjectContent', a false response causing fallback to the standard Json formatter : so my WriteStream(...) was never invoked.
The solution was to make sure my formatter could cope with ObjectContent.
Upvotes: 1