ASP.Net Core - клиентский форматтер имеет преимущество - PullRequest
0 голосов
/ 24 января 2019

Я последовал примеру здесь и написал свой клиентский форматтер ниже.Он работает нормально, однако проблема в том, что он всегда запускается первым и не учитывает, что он должен запускаться только тогда, когда заголовок 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));

...