2013-01-07 14 views
13

ho creato un controller API ASP.NET Web che restituisce un oggetto fortemente tipizzato su un'azione, come segue:Modificare intestazioni di risposta su Tipo di supporto Formatter per ASP.NET Web API

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

ho creato un BufferedMediaTypeFormatter per gestire il tipo iOSDevice:

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

mio problema è quando prendo tipo "text/html" (ad esempio, qualcuno tenta di accedere alle API dal proprio browser web), il tipo di risposta è "text/html "invece di" application/xml ". Voglio sovrascrivere il tipo di risposta in modo che l'utente ottenga una risposta "application/xml" anziché "text/html".

Non riesco nel tipo ApiController ad accedere alla proprietà "Response" che si trova sui normali controller MVC e sono in perdita. Come sovrascrivo il tipo di risposta per questa azione che viene gestita da un formattatore del tipo di supporto?

EDIT: UTILE NOTA

Cercavo questo in precedenza:

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; 

Ed è stato superiore mi è stato "uso improprio" le intestazioni.

Ma quando ho usato l'esempio di Filip qui sotto di impostare direttamente il contenuto, ha funzionato!

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

ContentType non è una risposta intestazione, è un'intestazione del payload. Quindi potresti fare response.Content.Headers.ContentType = ... –

risposta

18

Quando si scrive nello stream nel formattatore, le intestazioni sono già state inviate.

Si può fare questo:

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

o si può fare questo (aggiungi questo metodo per il vostro formattatore):

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

Ecco un esempio di come ho usato il SetDefaultContentHeaders con un costume formattatore: 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

Brillante! Ha funzionato! Tuttavia ... non è piaciuto questo: var response = Request.CreateResponse (HttpStatusCode.Accepted, device); \t \t \t response.Headers.Remove ("Content-Type"); \t \t \t response.Headers.Add ("Content-Type", "application/xml; charset = utf-8"); \t \t \t risposta di risposta; Ho dovuto farlo nel modo in cui hai detto, con l'impostazione della proprietà Content. Grazie!! –

+0

Domanda successiva. È possibile modificare il nome del file all'interno del programma di formattazione, in modo che il nome del file sia specifico per ogni richiesta, piuttosto che impostare generalmente su "ebook.mobi"? –

Problemi correlati