2013-11-14 1 views
37

Я пытаюсь получить выходные данные XML или JSON на основе ввода. Я использовал приведенный ниже код API WEB, но не смог точно выполнить вывод.Как заставить ASP.NET Web API возвращать данные JSON или XML на основе ввода?

public string Get(int id) 
{ 
    if (GlobalConfiguration.Configuration.Formatters.XmlFormatter == null) 
    { 
     GlobalConfiguration.Configuration.Formatters.Add(GlobalConfiguration.Configuration.Formatters.XmlFormatter); 
    } 
    if (GlobalConfiguration.Configuration.Formatters.JsonFormatter == null) 
    { 
     GlobalConfiguration.Configuration.Formatters.Add(GlobalConfiguration.Configuration.Formatters.JsonFormatter); 
    } 
    if (id == 1) 
    { 
     GlobalConfiguration.Configuration.Formatters.Remove(GlobalConfiguration.Configuration.Formatters.JsonFormatter);     
     GlobalConfiguration.Configuration.Formatters.XmlFormatter.UseXmlSerializer = true;     
    } 
    else 
    { 
     GlobalConfiguration.Configuration.Formatters.Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter); 
     GlobalConfiguration.Configuration.Formatters.JsonFormatter.UseDataContractJsonSerializer = true; 
    } 
    return "value"; 
} 

ответ

73

Добавить ниже код app_start событие в global.asax файле. В API Url добавить строку запроса:

GlobalConfiguration.Configuration.Formatters.JsonFormatter.MediaTypeMappings.Add(
    new QueryStringMapping("type", "json", new MediaTypeHeaderValue("application/json"))); 

GlobalConfiguration.Configuration.Formatters.XmlFormatter.MediaTypeMappings.Add(
    new QueryStringMapping("type", "xml", new MediaTypeHeaderValue("application/xml"))); 

.: например

for xml : http://localhost:49533/api/?type=xml 

for json: http://localhost:49533/api/?type=json 
+0

вот подсказка, если вам нужно использовать маршрут вместо QueryString, я создал пользовательский картограф наследования из «MediaTypeMapping» и переопределения «TryMatchMediaType» –

+1

Он не работает для маршрута 'http: // localhost: 49533/api/entity/1? type = xml ' – Marusyk

+0

Работает ли он с HTTP-маршрутизацией, например '[Route (" api/{type}/entity ")]'? – Lucas

9

То, что вы пытаетесь сделать, не будет работать в многопоточной среде. Вы не можете добавлять и удалять из коллекции форматировщиков по запросу. Вот лучший способ выполнить то, что вы хотите.

public HttpResponseMessage Get(int id) 
{ 
    Foo foo = new Foo(); 
    var content = new ObjectContent<Foo>(foo, 
        ((id == 1) ? Configuration.Formatters.XmlFormatter : 
           Configuration.Formatters.JsonFormatter)); 
    return new HttpResponseMessage() 
    { 
     Content = content 
    }; 
} 
+0

А я вижу, что это похоже на ответ, который я нашел, хороший – jamiebarrow

5

Если запрос определяет тип MIME, например application/json, то веб-апи будет формат ответа соответственно.

Если вы пытаетесь отлаживать свой веб-api вручную, используйте для этого тип инструмента Fiddler 2.

This article описывает концепцию.

+0

+1 Я бы предложил сделать это, а не пользовательский ввод строки запроса, поскольку это стандартный способ сделать это. – jamiebarrow

+0

Возможно, лучшая ссылка: http://www.asp.net/web-api/review/formats-and-model-binding/content-negotiation – jamiebarrow

1

QueryStringMapping` является хорошим решением, но мне нужно значение по умолчанию для типа.

для XML: localhost:49533/api/?type=xml

для JSON: localhost:49533/api/

Я решить эту ситуацию так:

GlobalConfiguration.Configuration.Formatters.XmlFormatter.SupportedMediaTypes.Clear(); 
var jSettings = new JsonSerializerSettings(); 

GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings = jSettings; 
GlobalConfiguration.Configuration.Formatters.XmlFormatter.MediaTypeMappings.Add(new QueryStringMapping("xml", "true", new MediaTypeHeaderValue("application/xml"))); 
3

Хотя принятый ответ на vijayjan15 кажется, что лучший способ пойти для вашей конкретной ситуации (то есть, используя MediaTypeMappings), вы можете альтернативно иметь два разных метода: один, который возвращает XML, и тот, который возвращает JSON. Чтобы сделать это, вы можете создать экземпляр контроллера конкретных HttpConfiguration (во избежание изменения в один GlobalConfiguration.Configuration):

public MyReturnType GetMyTypeAsXml() { 
    Configuration = new HttpConfiguration(); 
    Configuration.Formatters.Clear(); 
    Configuration.Formatters.Add(new XmlMediaTypeFormatter()); 

    return new MyReturnType(); 
} 

public MyReturnType GetMyTypeAsJson() { 
    Configuration = new HttpConfiguration(); 
    Configuration.Formatters.Clear(); 
    Configuration.Formatters.Add(new JsonMediaTypeFormatter()); 

    return new MyReturnType(); 
} 

я не уверен, сколько над головой есть в раскручивается новый экземпляр HttpConfiguration (Я подозреваю, что не много), но новый экземпляр поставляется с сборкой Formatters, заполненной по умолчанию, поэтому вам нужно очистить ее сразу после ее создания. Обратите внимание, что если вы не используете, используйте Configuration = new HttpConfiguration(), а вместо этого измените конфигурацию напрямую, она изменит свойство GlobalConfiguration.Configuration (так что это повлияет на все ваши другие методы WebApi - плохо!).

+0

Я думаю, что снова прочитайте ответ jyarbro;) – jamiebarrow

+1

Мой предложенный альтернативный ответ был основан на предположении, что автор вопроса либо не имел доступа к самому запросу (например, для изменения заголовков) или хотите указать XML или JSON, если запрос возник в браузере (в этом случае разные браузеры отправляют разные заголовки accept, чтобы FireFox показывал XML, тогда как IE будет тянуть как JSON - если он хочет быть явный, он не может полагаться на заголовки). ;-) – Kirkaiya

+0

Да, правда, я предполагал, что он контролировал запрос с проверкой на 'id == 1', но я предполагаю, что он просто попробовал это в примерном проекте, так что хорошая точка :) Я добавил ответ , думаю, я нашел лучший способ сделать это в другом сообщении SO. – jamiebarrow

8

Посмотрел на это немного больше, и нашел ответ в another post:

public HttpResponseMessage Get(int id) 
{ 
    string content = "value"; 

    if (id == 1) 
    { 
     return Request.CreateResponse<string>(HttpStatusCode.OK, content, Configuration.Formatters.JsonFormatter); 
    } 

    return Request.CreateResponse<string>(HttpStatusCode.OK, content, Configuration.Formatters.XmlFormatter); 
} 
+0

Теперь * это * на самом деле выглядит полезно! – Kirkaiya

+0

@ Kirkaiya Я заметил ответ Бадри после этого, они делают то же самое, что кажется, но это, похоже, имеет для меня гораздо больше смысла :) Спасибо! – jamiebarrow

6

Он также работает, чтобы заставить ПРИНЯТЬ заголовки. Отличный вариант, если вы не всегда возвращаетесь HttpResponseMessage's. Я.е

Request.Headers.Add("Accept", "text/json"); 
return Request.CreateResponse(HttpStatusCode.OK, yourobject); 

или

Request.Headers.Add("Accept", "application/xml"); 
return new Rss20FeedFormatter(feed); 
+0

Может быть добавлена ​​часть Request.Headers.Add на уровне контроллера – aemorales1

Смежные вопросы