13

ich eine ASP.NET Web-API-Controller erstellt haben, die eine stark typisierte Objekt auf eine Aktion zurückkehrt, wie folgt:ändern Antwortheader auf Medientyp Formatter für ASP.NET Web API

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

ich geschaffen habe, ein BufferedMediaTypeFormatter den Typ iOSDevice zu handhaben:

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(); 
    } 
} 

Mein Problem ist, wenn ich Typen „text/html“ fange (zB jemand versucht, die API von seinem Web-Browser zuzugreifen), der Antworttyp „text/html "statt" application/xml ". Ich möchte den Antworttyp überschreiben, sodass der Benutzer eine Antwort erhält, die "application/xml" anstelle von "text/html" lautet.

Ich kann nicht in der ApiController Typ bekommen Zugriff auf die Eigenschaft "Response", die auf regulären MVC-Controller ist und ich bin ratlos. Wie überschreibe ich den Antworttyp für diese Aktion, die von einem Medientyp formatiert wird?

EDIT: hilfreicher Hinweis

Ich habe versucht, dies vorher:

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; 

Und behauptet, ich "missbräuchlich" die Header wurde.

Aber als ich Filip's Beispiel unten verwendete, um Inhalt direkt zu setzen, funktionierte es!

+3

Content ist keine Antwort Header, es ist ein Payload-Header. So könnten Sie response.Content.Headers.ContentType = ... –

Antwort

18

Wenn Sie im Formatierer zum Streamen schreiben, wurden bereits Header gesendet.

Sie können dies tun:

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; 
    } 

oder Sie können dies tun (diese Methode, um Ihre Formatierer hinzufügen):

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

Hier ist ein Beispiel, wie ich die SetDefaultContentHeaders mit einem benutzerdefinierten verwendet Formatierer: 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); 
     } 
    } 
+0

Brilliant! Es funktionierte! Wie auch immer ... es hat mir nicht gefallen: var response = Request.CreateResponse (HttpStatusCode.Accepted, device); \t \t \t response.Headers.Remove ("Inhaltstyp"); \t \t \t response.Headers.Add ("Inhaltstyp", "application/xml; charset = utf-8"); \t \t \t Antwort zurücksenden; Ich musste es tun, wie Sie gesagt haben, mit der Einstellung der Content-Eigenschaft. Vielen Dank!! –

+0

Folgefrage. Ist es möglich, den Dateinamen innerhalb des Formatierers zu ändern, sodass der Dateiname für jede Anfrage spezifisch ist und nicht allgemein auf "ebook.mobi" gesetzt wird? –