Каковы наилучшие методы ручного управления MediaTypeFormatter в веб-API ASP MVC?

У меня есть служба веб-API ASP MVC, и мой метод должен возвращать данные в определенном формате (JSON, XML и т. Д.). Формат ответа зависит от метода и не зависит от предпочтений клиента.
Я использую HttpResponseMessage и ObjectContent, и мне нужно установить MediaTypeFormatter для ObjectContent.
Я могу это сделать так:

new ObjectContent<MyDataContract>(data, new JsonMediaTypeFormatter())

или так:

new ObjectContent<MyDataContract>(data, Configuration.Formatters.FirstOrDefault(f => f.GetType() == typeof(JsonMediaTypeFormatter)))

Ни один из них не выглядит хорошо.
Первый создает новый объект для каждого запроса.
Второй использует поиск, и здесь это выглядит неуместным.
Может ли кто-нибудь знать лучшее решение моей проблемы?


person Alexander    schedule 17.11.2015    source источник
comment
Я бы не стал беспокоиться о создании нового объекта для каждого запроса, если он не влияет измеримым образом. В любом случае ничто не мешает вам сохранить его в [ThreadLocale] статической переменной или, проще говоря, в static ThreadLocal<JsonMediaTypeFormatter> _jsonMediaTypeFormatter;   -  person Adriano Repetti    schedule 17.11.2015
comment
Я использую веб-API, и мой метод должен возвращать JSON - нет. Ваш метод должен возвращать запрошенный тип данных, вы можете сделать этот json по умолчанию: stackoverflow.com/a/20556625/2181514 < / а>   -  person freedomn-m    schedule 17.11.2015
comment
Ни один из них не выглядит красивым - добро пожаловать в MVC!   -  person freedomn-m    schedule 17.11.2015
comment
@AdrianoRepetti JsonMediaTypeFormatter уже сохранен в Configuration.Formatters, поэтому я не думаю, что эта идея намного лучше. У меня нет серьезных проблем с моим решением, но я хочу, чтобы оно было красивее :)   -  person Alexander    schedule 17.11.2015
comment
@ freedomn-m У меня есть требования, чтобы некоторые мои методы возвращали JSON, некоторые XML, и это не должно зависеть от предпочтений клиента   -  person Alexander    schedule 17.11.2015
comment
... и вы не можете напрямую выбрать его через Configuration.Formatters.JsonMediaTypeFormatter, да, вы просто избегаете поиска. Вот почему я бы не стал возиться с этим (если у вас нет причин сделать его потокобезопасным).   -  person Adriano Repetti    schedule 17.11.2015
comment
Затем просто верните JSON / XML в виде строки из действия (т.е. закодируйте в действии) и забудьте об использовании MediaTypeFormatters. Если это иногда JSON, иногда XML, тогда не стоит менять значения по умолчанию.   -  person freedomn-m    schedule 17.11.2015
comment
@ freedomn-m это всегда XML и всегда JSON для каждого метода. Сериализовать его вручную и вернуть в виде строки (или массива байтов) - действительно интересная идея. Спасибо   -  person Alexander    schedule 17.11.2015
comment
Вот вам еще один вариант: stackoverflow.com/questions/686753/ вернуть данные как обычно, а затем использовать фильтр действий (атрибут действия) для преобразования в JSON / XML непосредственно перед отправка обратно клиенту. Это означает, что у вас не так много return Json(), но вместо этого к определению действия применено [Json].   -  person freedomn-m    schedule 17.11.2015


Ответы (2)


Почему вы не используете IHttpActionResult и не возвращаете Ok ()? Вам явно нужен HttpResponseMessage? Также вы хотите всегда возвращать JSON или нет в зависимости от типа контента, которого ожидает клиент?

Если вы хотите всегда возвращать JSON и использовать IHttpActionResult в своем файле WebApiConfig, вы можете добавить следующее:

config.Formatters.Clear();
config.Formatters.Add(new JsonMediaTypeFormatter());

Таким образом, API всегда будет возвращать JSON, а в вашем контроллере вы можете вернуть только OK:

return this.Ok(data); // will be enough, no need to specify the content type

В противном случае, если вы настаиваете на HttpResponseMessage, вы можете унаследовать класс ObjectContent и использовать его (код пишется на лету, могут потребоваться некоторые настройки)

public class JsonObjectContent<T> : ObjectContent<T>
{
    public JsonObjectContent(T data) : base(data, new JsonMediaTypeFormatter())
    {
    }
}

И в вашем контроллере вы скажете

new JsonObjectContent<MyDataContract>(data)
person Ивайло Кенов    schedule 17.11.2015
comment
Я обновил свой вопрос, и теперь он должен быть более ясным. JsonObjectContent по-прежнему создавать новое средство форматирования для каждого запроса. - person Alexander; 17.11.2015
comment
Что ж, с обновленным вопросом первый комментарий Адриано Репетти меня устраивает, если вы не хотите создавать экземпляр средства форматирования для каждого запроса. - person Ивайло Кенов; 17.11.2015

Вы можете установить в файле webApiConfig.

  config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));

Также можно установить MediaType для ответа при возврате данных -

     [HttpGet]
      public HttpResponseMessage GetJson()
      {

        var result = new List<string>();

        for (int i = 0; i < 50; i++)

            result.Add("Hello World");

       return Request.CreateResponse(HttpStatusCode.OK, result, new 
        MediaTypeHeaderValue("application/json"));

    }
person Shivprasad P    schedule 18.02.2019