Согласование содержимого в веб-API ASP.NET

Я переношу веб-службу на ASP.NET Web Api 2 и сталкиваюсь с проблемой почти на первом же препятствии.

Я хочу сделать это:

public class SomeController : ApiController
{
    [Route("some\url")]
    public object Get()
    {
        return { Message = "Hello" };
    }
}

И иметь возможность запрашивать у службы «application/json» или «application/xml» (или любой другой возможный формат, например Message Pack) и получать сериализованный ответ. Но, кажется, это работает только для JSON.

Я прочитал это и видел документация, в которой четко указано, что инфраструктура не может обрабатывать сериализацию анонимных типов в XML (серьезно) и что решение состоит в том, чтобы не использовать XML (серьезно).

Когда я пытаюсь вызвать это и запросить XML в качестве типа ответа, я получаю

The 'ObjectContent`1' type failed to serialize the response body for content type 'application/xml; charset=utf-8'.

Я не удаляю поддержку для клиентов, желающих запросить XML, но я действительно не могу найти обходной путь для этого - что я могу сделать?

Изменить

Я добавил это:

System.Web.Http.GlobalConfiguration.Configuration.Formatters.XmlFormatter.SupportedMediaTypes.Clear();
config.Formatters.Insert(0, new System.Net.Http.Formatting.JsonMediaTypeFormatter());
config.Formatters.Insert(0, new System.Net.Http.Formatting.XmlMediaTypeFormatter());

согласно ответу Далорзо, но это не имело значения.

Для пояснения, служба работает абсолютно нормально, когда я вызываю ее, используя заголовок accept application/json, но бомбит, когда я вызываю ее с заголовком accept application/xml.


person Greg Smith    schedule 19.05.2014    source источник
comment
Вы уверены, что ваш код скомпилирован?   -  person Toan Nguyen    schedule 20.05.2014
comment
WebApi - это служба REST, можете ли вы подробно рассказать о маршрутизации и методе (GET | POST), которые вы имеете в виду, когда получили ошибку, как вы их вызываете?   -  person Dalorzo    schedule 20.05.2014
comment
Да, код компилируется. Это стандартный GET-запрос. Маршрут подробно описан в вопросе.   -  person Greg Smith    schedule 20.05.2014


Ответы (3)


У вас есть 3 варианта:

  1. Создайте класс с правильным именем и верните объект вместо анонимного типа.
  2. Или, если вы хотите вернуть анонимный экземпляр, вам следует удалить средство форматирования XML, поскольку анонимные типы не поддерживаются XML Formatter

  3. Создайте свой собственный модуль форматирования, наследующий от MediaTypeFormatter или BufferedMediaTypeFormatter.

person Toan Nguyen    schedule 19.05.2014

Вы можете сделать это по следующему коду:

public HttpResponseMessage GetTestData()
        {        
               var testdata = (from u in context.TestRepository.Get().ToList()                            
                            select
                                 new Message
                                 {
                                     msgText = u.msgText                                    
                                 });    
                return ActionContext.Request.CreateResponse(HttpStatusCode.OK, testdata);
        }
person Chandrika Prajapati    schedule 20.05.2014

Пожалуйста, просмотрите свой маршрут API в Chrome. Chrome по умолчанию показывает вывод в формате XML. Если этого не происходит, это означает, что ваша служба запрещает формат XML с использованием форматирования мультимедиа.

И в этом случае вы должны искать свой WebApiConfig. Если там ничего нет, добавьте этот файл в свой проект

using System.Net.Http.Formatting;
using System.Collections.Generic;
using System.Net.Http;
using System;
using System.Linq;
using System.Net.Http.Headers;
namespace ExampleApp.Infrastructure
{
    public class CustomNegotiator : DefaultContentNegotiator
    {
        public override ContentNegotiationResult Negotiate(Type type, HttpRequestMessage request, IEnumerable<MediaTypeFormatter> formatters)
        {
            if(request.Headers.UserAgent.Where(x=>x.Product!=null&& x.Product.Name.ToLower().Equals("chrome")).Count() > 0)
            {
                return new ContentNegotiationResult(new JsonMediaTypeFormatter(), new MediaTypeHeaderValue("application/xml"));
            }
            else
            {
                return base.Negotiate(type, request, formatters);
            }
        }
    }
}

и в WebApiConfig.cs добавить:

config.Services.Replace(typeof(IContentNegotiator), new CustomNegotiator());
person Rajat    schedule 25.12.2015