Я хотел бы установить формат по умолчанию для ServiceStack для JSON, в отличие от отформатированного ответа в формате HTML, который обычно возвращает, когда к службе обращаются из браузера. Я знаю, что это можно указать по каждому запросу, отправив параметр? Format = json или установив заголовок Accept в application/json. Есть ли способ изменить это, не полагаясь на эти подсказки из запроса?
Формат по умолчанию для ServiceStack
Ответ 1
В дополнение к указанию в QueryString с ? format = json, путем добавления формата .ext до конца маршрута, например: /rockstars.json, или указав заголовок HTTP (в вашем HttpClient): Accept: application/json
.
В противном случае, если ваш HttpClient не отправляет заголовок Accept, вы можете указать JSON в качестве типа содержимого по умолчанию в своем AppHost с помощью:
SetConfig(new HostConfig {
DefaultContentType = MimeTypes.Json
});
Здесь перечислены все параметры конфигурации в ServiceStack.
Проблема при вызове веб-служб из веб-браузера заключается в том, что они обычно запрашивают Accept: text/html
, а не JSON, который по контракту ServiceStack обязывает, возвращая HTML-код, если он включен.
Чтобы вернуть JSON, вы также можете отключить функцию HTML:
SetConfig(new HostConfig {
EnableFeatures = Feature.All.Remove(Feature.Html),
});
Различные способы указания типа содержимого ответа
В противном случае, если вы хотите переопределить заголовок Accept, вы можете заставить службу всегда возвращать json любым из этих способов: Настроить HTTP-ответ, например:
Использование фильтра (встроенный AddHeader):
[AddHeader(ContentType=MimeTypes.Json)]
public object Any(Request request) { ... }
Установка ответа в службе:
public object Any(Request request)
{
base.Response.ContentType = MimeTypes.Json;
return dto;
}
Возвращение оформленного ответа:
return new HttpResult(dto, MimeTypes.Json);
Ответ 2
Я использую PreRequestFilter для принудительного ответа JSON на браузер. Вы все еще видите? Format = json в querystring, но это полезно, если вы отключили html и xml.
this.PreRequestFilters.Add( (req, res) =>
{
const string queryString = "format=json";
var jsonAccepted = req.AcceptTypes.Any(t => t.Equals(ContentType.Json, StringComparison.InvariantCultureIgnoreCase));
var jsonSpecifiedOnQuerystring = !string.IsNullOrEmpty(req.QueryString["format"]) && req.QueryString["format"].Equals("json", StringComparison.InvariantCultureIgnoreCase);
if (!jsonAccepted && !jsonSpecifiedOnQuerystring)
{
var sb = new StringBuilder(req.AbsoluteUri);
sb.Append(req.AbsoluteUri.Contains("?") ? "&" : "?");
sb.Append(queryString);
res.RedirectToUrl(sb.ToString(), HttpStatusCode.SeeOther);
res.Close();
}
});
Ответ 3
Поздно к вопросу, но поскольку я не мог найти ответ нигде, я, наконец, понял его из исходного кода ServiceStack:)
Самый простой способ, которым я нашел по умолчанию Json вместо Html из браузера, был следующим:
HttpRequestExtensions.PreferredContentTypes = new[] { MimeTypes.Json, MimeTypes.Xml };
Вызовите это при запуске своего приложения, и оно переопределит стандартные типы сервисов ServiceStack и начнет с json (который будет работать с вашими запросами браузера, так как/будет соответствовать ему).
Обратите внимание, что вы все равно должны отключить Html и сделать Json типом mime по умолчанию:
SetConfig(new HostConfig {
DefaultContentType = MimeTypes.Json
EnableFeatures = Feature.All.Remove(Feature.Html),
});
Для любопытных: ServiceStack использует внутренне HttpRequestExtensions.GetResponseContentType
(см. HttpRequestExtensions.cs
), который перебирает предпочтительные типы контента. Поскольку он содержит MimeTypes.Html
, он будет захватывать первый тип accept из браузера (text/html
) и игнорировать все, что происходит. Переопределяя это, text/html
не рассматривается как предпочтительный тип содержимого, а затем переходит к */*
, который по умолчанию соответствует json
, как ожидалось.