OData Web API - ODataMediaTypeFormatter MediaTypeResolver больше не существует

Веб-API OData v7. Я пишу пользовательский форматтер для CSV, Excel и т.д. У меня нет связи с тем, как я указываю свой пользовательский форматер (ODataMediaTypeFormatter) на мои собственные классы, где я изменяю вывод.

CustomFormatter: ODataMediaTypeFormatter - имел MessageWriterSettings.MediaTypeResolver, которого больше не существует в v. 7

Когда я отлаживаюсь, я попадаю на GetPerRequestFormatterInstance, и после этого он умирает с не найденным поддерживаемым типом MIME, который соответствует типу содержимого ответа.

Я не могу понять поток - как связать его с моим обычным (ODataWriter) писателем (CSV, или что я хочу создать).

Например, из примера на git:

public class CustomFormatter : ODataMediaTypeFormatter
{
    private readonly string csvMime = ;

    public CustomFormatter(params ODataPayloadKind[] kinds)
        : base(kinds) {
        //----no longer exists in 7
        //MessageWriterSettings.MediaTypeResolver = new MixResolver();

        SupportedEncodings.Add(Encoding.UTF8);
        SupportedEncodings.Add(new UTF8Encoding(encoderShouldEmitUTF8Identifier: false));
        SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/csv"));            
    }
}

public class MixResolver : ODataMediaTypeResolver
{
    public override IEnumerable<ODataMediaTypeFormat> GetMediaTypeFormats(ODataPayloadKind payloadKind)
    {
        if (payloadKind == ODataPayloadKind.Resource || payloadKind == ODataPayloadKind.ResourceSet)
        {
            return CsvMediaTypeResolver.Instance.GetMediaTypeFormats(payloadKind);
        }
        return base.GetMediaTypeFormats(payloadKind);
    }
}

public class CsvMediaTypeResolver : ODataMediaTypeResolver
{
    private static readonly CsvMediaTypeResolver instance = new CsvMediaTypeResolver();
    private readonly ODataMediaTypeFormat[] mediaTypeFormats =
    {
    new ODataMediaTypeFormat(new ODataMediaType("text", "csv"), new CsvFormat())
};

public class CsvMediaTypeResolver : ODataMediaTypeResolver
{
    private static readonly CsvMediaTypeResolver instance = new CsvMediaTypeResolver();
    private readonly ODataMediaTypeFormat[] mediaTypeFormats = { new ODataMediaTypeFormat(new ODataMediaType("text", "csv"), new CsvFormat())};
    private CsvMediaTypeResolver() { }
    public static CsvMediaTypeResolver Instance { get { return instance; } }
    public override IEnumerable<ODataMediaTypeFormat> GetMediaTypeFormats(ODataPayloadKind payloadKind)
    {
        if (payloadKind == ODataPayloadKind.Resource || payloadKind == ODataPayloadKind.ResourceSet)
        {
            return mediaTypeFormats.Concat(base.GetMediaTypeFormats(payloadKind));
        }
        return base.GetMediaTypeFormats(payloadKind);
    }
}


public class CsvWriter : ODataWriter
{
    // Etc..
}

Разъединение происходит с ODataMediaTypeFormatter и CsvMediaTypeResolver. Как мне связать ODataMediaTypeFormatter с моим распознавателем?

Ответ 1

Я решил это с помощью CsvOutputContext и CsvWriterDemo, описанных в примерах в Microsoft.OData.Core

Обновлен пример кода

public CsvOutputContext(
   ODataFormat format,
   ODataMessageWriterSettings settings,
   ODataMessageInfo messageInfo,
   bool synchronous)
   : base(format, settings, messageInfo.IsResponse, synchronous, 
     messageInfo.Model, messageInfo.UrlResolver)

   {
     this.stream = messageInfo.GetMessageStream();
     this.Writer = new StreamWriter(this.stream);
   }
}

private static void CsvWriterDemo()
{
   EdmEntityType customer = new EdmEntityType("ns", "customer");
   var key = customer.AddStructuralProperty("Id", EdmPrimitiveTypeKind.Int32);
   customer.AddKeys(key);
   customer.AddStructuralProperty("Name", EdmPrimitiveTypeKind.String);

   ODataEntry entry1 = new ODataEntry()
   {
       Properties = new[]
       {
           new ODataProperty(){Name = "Id", Value = 51}, 
           new ODataProperty(){Name = "Name", Value = "Name_A"}, 
       }
   };

   ODataEntry entry2 = new ODataEntry()
   {
       Properties = new[]
       {
           new ODataProperty(){Name = "Id", Value = 52}, 
           new ODataProperty(){Name = "Name", Value = "Name_B"}, 
       }
   };

   var stream = new MemoryStream();
   var message = new Message { Stream = stream };
   // Set Content-Type header value
   message.SetHeader("Content-Type", "text/csv");
   var settings = new ODataMessageWriterSettings
   {
       // Set our resolver here.
       MediaTypeResolver = CsvMediaTypeResolver.Instance,
       DisableMessageStreamDisposal = true,
   };
   using (var messageWriter = new ODataMessageWriter(message, settings))
   {
       var writer = messageWriter.CreateODataFeedWriter(null, customer);
       writer.WriteStart(new ODataFeed());
       writer.WriteStart(entry1);
       writer.WriteEnd();
       writer.WriteStart(entry2);
       writer.WriteEnd();
       writer.WriteEnd();
       writer.Flush();
   }

   stream.Seek(0, SeekOrigin.Begin);
   string msg;
   using (var sr = new StreamReader(stream)) { msg = sr.ReadToEnd(); }
   Console.WriteLine(msg);
}