1

MediaTypeFormatter画像の内部表現をpng/jpeg/etcに変換するがあります。誰かがそれを求めた場合。ただし、WriteToStreamAsyncimage / pngまたはacceptヘッダーに類似したものを追加しない限り、呼び出されることはありません。

まず、簡潔にするためにいくつかの重要なビットを削除した、私のwebapiメソッドを次に示します。

public ImageFormatter.BinaryImage GetImage(int cId, int iId)
{
    ....

    using (var input = iFIO.OpenRead())
    {
        input.Read(b.data, 0, (int)iFIO.Length);
    }

    // With this next line my mediatypeformatter is correctly called.
    Request.Headers.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("image/png"));

    return b;
}

そして、これが私の書き込み部分ですMediaTypeFormatter(読み取り部分もあり、実際にはうまく機能します)。

namespace PivotWebsite.MediaFormatters
{
    public class ImageFormatter : MediaTypeFormatter
    {
        public class BinaryImage
        { 
            public byte[] data;
            public string metaData;
        }

        public ImageFormatter()
        {
            SupportedMediaTypes.Add(new MediaTypeHeaderValue("image/jpg"));
            SupportedMediaTypes.Add(new MediaTypeHeaderValue("image/jpeg"));
            SupportedMediaTypes.Add(new MediaTypeHeaderValue("image/png"));
        }

        public override bool CanWriteType(Type type)
        {
            return true;
        }

        public override async Task WriteToStreamAsync(Type type, object value, Stream writeStream, HttpContent content, TransportContext transportContext)
        {
            var b = value as BinaryImage;
            if (b == null)
                throw new InvalidOperationException("Can only work with BinaryImage types!");

            await writeStream.WriteAsync(b.data, 0, b.data.Length);
        }
    }
}

私ができると期待していたのは、でWriteToStreamAsync、送信ヘッダーを変更して、Content-Typeを「image / png」(またはデータ型によっては何でも)として含めることでした。

http://my.testdomain.net:57441/api/Images?cID=1&iID=1ただし、「 」のようなURLを使用してWebブラウザーからこれを呼び出すと、WriteToStreamAsync呼び出されることはありません(受け入れられるヘッダーは{text / html、application / xhtml + xml、* / *}としてリストされます)。適切な画像タイプを追加する上記の行を追加すると、すべてが期待どおりに呼び出されます。

ここで何が欠けていますか?「*/*」の受け入れられたヘッダーは、私のメディアフォーマッターをトリガーするはずでしたね?または...WebAPIの配管に関する基本的なことを見逃していますか?

4

2 に答える 2

2

Acceptヘッダーが" / "の場合、画像フォーマッターを常に使用しますか?その場合は、最初にフォーマッターを次のようにフォーマッターコレクションに挿入する必要があります。

config.Formatters.Insert(0, new ImageFormatter());

あなたの場合のように正確なAcceptヘッダーの一致がない場合に起こることは、タイプを書き込むことができる最初のフォーマッターがオブジェクトをシリアル化するために選択されることです。したがって、最初にフォーマッタを登録すると、それが使用されます。

ただし、これはすべてのコントローラーに影響するため、意図しない副作用が発生する可能性があります。CanWriteType実装を変更して、BinaryImageの場合にのみtrueを返すようにすることをお勧めします。これにより、フォーマッタは、それがリターンタイプである場合にのみ使用されるようになります。

もう1つの方法は、HttpResponseMessageを返すことにより、アクションでフォーマッターを直接選択することです。

return Request.CreateResponse(HttpStatusCode.OK, image, new ImageFormatter());

つまり、基本的には、「このアクションでは、コンテンツタイプ、ヘッダーの受け入れなどに関係なく、常に画像フォーマッターを使用する必要があります」ということです。常に画像を返すだけで、フォーマッタでシリアル化する必要がある場合は、これが妥当な場合があります。

于 2013-03-24T15:45:37.977 に答える
0

CsvFormatterを作成していますが、ブラウザーからAPIを呼び出して、ファイルのダウンロードをトリガーできるようにしたいと考えています。Acceptヘッダーを制御できなかったため、拡張機能を使用してCSVフォーマッターをトリガーしたかったのですが、XMLフォーマッターはリクエストを取得し続けました。「text/html」メディアタイプを追加することで、CSV拡張機能を処理できることがわかりました。うまくいけば、これは将来的に他の問題を引き起こさないでしょう:)。

public CsvFormatter()
{
    var header = new MediaTypeHeaderValue("text/csv");
    SupportedMediaTypes.Add(header);
    MediaTypeMappings.Add(new UriPathExtensionMapping("csv", header));

    // From Chrome: Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
    // Allow the formatter to run from a standard browser request.
    header = new MediaTypeHeaderValue("text/html");
    SupportedMediaTypes.Add(header);
    MediaTypeMappings.Add(new UriPathExtensionMapping("csv", header));
}
于 2014-03-12T03:13:29.407 に答える