Изменение заголовков ответов на форматах типа Media для веб-API ASP.NET
Я создал контроллер веб-API ASP.NET, который возвращает строго типизированный объект в действии, как показано ниже:
// GET api/iosdevices/5
public iOSDevice Get(string id) {
return new iOSDevice();
}
Я создал BufferedMediaTypeFormatter для обработки типа 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();
}
}
Моя проблема в том, что когда я поймаю тип "text/html" (например, кто-то пытается получить доступ к API из своего веб-браузера), тип ответа "text/html" вместо "application/xml". Я хочу переопределить тип ответа, чтобы пользователь получил ответ "application/xml" вместо "text/html" .
Я не могу в типе ApiController получить доступ к свойству "Ответ", который находится на обычных контроллерах MVC, и я в недоумении. Как переопределить тип ответа для этого действия, которое обрабатывается форматом медиа-типа?
РЕДАКТИРОВАТЬ: ПОМОЩЬ ПРИМЕЧАНИЕ
Я пытался это сделать ранее:
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;
И он утверждал, что я "неправильно использовал" заголовки.
Но когда я использовал пример Filip ниже для настройки содержимого напрямую, он работает!
var response = Request.CreateResponse();
response.Content = new ObjectContent<iOSDevice>(device, new iOSDeviceXmlFormatter());
return response;
Ответы
Ответ 1
Когда вы пишете поток в форматтере, заголовки уже отправлены.
Вы можете сделать это:
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);
}
}