Я последовал примеру здесь и написал свой клиентский форматтер ниже.Он работает нормально, однако проблема в том, что он всегда запускается первым и не учитывает, что он должен запускаться только тогда, когда заголовок Accept имеет текст / csv.
public class CSVFormatter : TextOutputFormatter
{
private string FileName { get; set; }
public CSVFormatter()
{
SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse("text/csv"));
SupportedEncodings.Add(Encoding.UTF8);
SupportedEncodings.Add(Encoding.Unicode);
}
protected override bool CanWriteType(Type type)
{
return IsTypeOfIEnumerable(type);
}
private bool IsTypeOfIEnumerable(Type type)
{
foreach (Type interfaceType in type.GetInterfaces())
{
if (interfaceType == typeof(IEnumerable))
return true;
}
return false;
}
public override Task WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding)
{
IServiceProvider serviceProvider = context.HttpContext.RequestServices;
var response = context.HttpContext.Response;
var buffer = new StringBuilder();
var value = context.Object;
var type = context.ObjectType;
WriteData(type, value, buffer, response);
return response.WriteAsync(buffer.ToString());
}
private void WriteData(Type type, object value, StringBuilder buffer, HttpResponse response)
{
//NOTE: We have check the type inside CanWriteType method. If request comes this far, the type is IEnumerable. We are safe.
Type itemType = type.GetGenericArguments()[0];
//Write out columns
buffer.AppendLine(string.Join<string>(",", itemType.GetProperties().Select(x => x.Name.ToLower())));
foreach (var obj in (IEnumerable<object>)value)
{
var vals = obj.GetType().GetProperties().Select(pi => new { Value = pi.GetValue(obj, null) });
string valueLine = string.Empty;
foreach (var val in vals)
{
var columnValue = val.Value;
valueLine = string.Concat(valueLine, columnValue, ",");
}
valueLine = valueLine.Substring(0, valueLine.Length - 1);
buffer.AppendLine(valueLine);
}
}
}
Я добавил его в Starup.cs следующим образом:
services.AddMvc(options =>
{
options.RespectBrowserAcceptHeader = true;
options.OutputFormatters.Insert(0, new CSVFormatter());
})
До ядра Asp.net, в .Net я запускал свой Custom Formatter только тогда, когда мне это было нужно, указав определенную строку запроса " format = csv " for.eg
Итак, пара вопросов:
- Как я могу заставить его работать только тогда, когда я хочу.
- Также я могу передать имя файла в строке или заголовке запроса и прочитатьдобавьте его в пользовательский форматтер и добавьте вот так.
headers.Add("Content-Disposition", string.Format("attachment; filename={0}", FileName));