15

次のように、アクションで厳密に型指定されたオブジェクトを返すASP.NETWebAPIコントローラーを作成しました。

// GET api/iosdevices/5
public iOSDevice Get(string id) {
  return new iOSDevice();
}

タイプiOSDeviceを処理するためにBufferedMediaTypeFormatterを作成しました。

public class iOSDeviceXmlFormatter : BufferedMediaTypeFormatter
{
    public iOSDeviceXmlFormatter() {
        SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/xml"));
        SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/xml"));
        SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));
    }

    public override void WriteToStream(Type type, object value, Stream writeStream, HttpContent content) {
        content.Headers.ContentType = new MediaTypeHeaderValue("application/xml");
        iOSDevice device = (iOSDevice)value;
        using (XmlWriter writer = XmlWriter.Create(writeStream)) {
            writer.WriteStartElement("iOSDevice");
            if (device.identifierForVendor != Guid.Empty) {
                writer.WriteElementString("identifierForVendor", device.identifierForVendor.ToString());
                writer.WriteElementString("userInterfaceIdiom", device.userInterfaceIdiom);
                writer.WriteElementString("systemName", device.systemName);
                writer.WriteElementString("systemVersion", device.systemVersion);
                writer.WriteElementString("model", device.model);
            }
            writer.WriteEndElement();
        }
        writeStream.Close();
    }
}

私の問題は、タイプ「text / html」をキャッチした場合(たとえば、誰かが自分のWebブラウザーからAPIにアクセスしようとした場合)、応答タイプが「application/xml」ではなく「text/html」になることです。ユーザーが「text/html」ではなく「application/xml」の応答を受け取るように、応答タイプをオーバーライドしたいと思います。

ApiControllerタイプでは、通常のMVCコントローラーにある「Response」プロパティにアクセスできず、途方に暮れています。メディアタイプフォーマッターによって処理されているこのアクションの応答タイプをオーバーライドするにはどうすればよいですか?

編集:役立つメモ

私は以前これを試していました:

var response = Request.CreateResponse<iOSDevice>(HttpStatusCode.Accepted, device);
response.Headers.Remove("Content-Type");
response.Headers.Add("Content-Type", "application/xml; charset=utf-8");
return response;

そして、それは私がヘッダーを「誤用している」と主張しました。

しかし、コンテンツを直接設定する以下のフィリップの例を使用すると、うまくいきました!

var response = Request.CreateResponse();
response.Content = new ObjectContent<iOSDevice>(device, new iOSDeviceXmlFormatter());
return response;
4

1 に答える 1

22

フォーマッタでストリームに書き込む場合、ヘッダーはすでに送信されています。

あなたはこれを行うことができます:

    public HttpResponseMessage Get(string id) {
    {
        var value = new iOSDevice();
        var response = Request.CreateResponse();
        response.Content = new ObjectContent(typeof(iOSDevice), value, new iOSDeviceXmlFormatter());
        //set headers on the "response"
        return response;
    }

または、これを行うことができます(このメソッドをフォーマッターに追加します):

    public override void SetDefaultContentHeaders(Type type, HttpContentHeaders headers, string mediaType)
    {
        base.SetDefaultContentHeaders(type, headers, mediaType);
        headers.ContentType = new MediaTypeHeaderValue("application/xml");
    }

SetDefaultContentHeadersカスタムフォーマッターでの 使用例を次に示します。http: //www.strathweb.com/2012/09/generate-kindle-mobi-ebooks-with-your-asp-net-web-api/

   public override void SetDefaultContentHeaders(Type type, HttpContentHeaders headers, MediaTypeHeaderValue mediaType)
   {
      if (CanWriteType(type) && mediaType.MediaType == supportedMediaType)
      {
         headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
         headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
         headers.ContentDisposition.FileName = "ebook.mobi";
      }
      else
      {
         base.SetDefaultContentHeaders(type, headers, mediaType);
      }
   }
于 2013-01-07T19:20:01.927 に答える