Change Response Headers on Media Type Formatter for ASP.NET Web API
When you write to stream in the formatter, headers have been already sent.
You can do this:
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;
}
or you can do this (add this method to your formatter):
public override void SetDefaultContentHeaders(Type type, HttpContentHeaders headers, string mediaType)
{
base.SetDefaultContentHeaders(type, headers, mediaType);
headers.ContentType = new MediaTypeHeaderValue("application/xml");
}
Here is an example on how I used the SetDefaultContentHeaders
with a custom formatter:
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);
}
}
Allison A
Updated on January 08, 2020Comments
-
Allison A over 4 years
I have created an ASP.NET web API controller that is returning a strongly typed object on an action, as follows:
// GET api/iosdevices/5 public iOSDevice Get(string id) { return new iOSDevice(); }
I have created a BufferedMediaTypeFormatter to handle the type 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(); } }
My problem is when I catch type "text/html" (e.g. someone attempts to access the API from his or her web browser), the response type is "text/html" instead of "application/xml". I want to override the response type so that the user gets a response that is "application/xml" instead of "text/html".
I cannot in the ApiController type get access to the "Response" property that is on regular MVC controllers and I am at a loss. How do I override the response type for this action that is being handled by a media type formatter?
EDIT: HELPFUL NOTE
I was trying this previously:
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;
And it claimed I was "misusing" the headers.
But when I used Filip's example below of setting Content directly, it worked!
var response = Request.CreateResponse(); response.Content = new ObjectContent<iOSDevice>(device, new iOSDeviceXmlFormatter()); return response;
-
Allison A over 11 yearsBrilliant! It worked! However... it didnt like this: 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; I had to do it the way you said to, with setting the Content property. Thank you!!
-
THX-1138 almost 9 yearsFollow up question. Is it possible to change file name from within formatter, so that file name is specific to each request, rather than set generally to "ebook.mobi"?