Сериализация массива объектов в JSON в WCF для соответствия OpenSearch
Я пытаюсь написать сервис предложений OpenSearch, который соответствует спецификации OpenSearch.
http://www.opensearch.org/Specifications/OpenSearch/Extensions/Suggestions
Эта спецификация требует, чтобы сервис возвращал массив JSON с первым элементом, являющимся строкой, а следующие элементы - массивами строк. Я могу получить это почти там, возвращая массив строк (string[][]) и имея WCF сериализовать это в JSON. Однако, чтобы соответствовать спецификации, я попытался вернуть массив объектов (object[]), первый из которых был строкой, а остальные - массивами строк (string[]).
Всякий раз, когда я пытаюсь вернуть массив объектов, он не работает, например, так:
Из сервиса:
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class SuggestionService : ISuggestionService
{
public object[] Search(string searchTerms)
{
SearchSuggestions = new object[4];
SearchText = searchTerms;
SearchSuggestions[0] = SearchText;
Text = new string[10];
Urls = new string[10];
Descriptions = new string[10];
// Removed irrelevant ADO.NET code
while (searchResultReader.Read() && index < 10)
{
Text[index] = searchResultReader["Company"].ToString();
Descriptions[index] = searchResultReader["Company"].ToString();
Urls[index] = "http://dev.localhost/Customers/EditCustomer.aspx?id=" +
searchResultReader["idCustomer"];
index++;
}
SearchSuggestions[1] = Text;
SearchSuggestions[2] = Descriptions;
SearchSuggestions[3] = Urls;
return SearchSuggestions;
}
[DataMember]
public string SearchText { get; set; }
[DataMember]
public string[] Text { get; set; }
[DataMember]
public string[] Descriptions { get; set; }
[DataMember]
public string[] Urls { get; set; }
[DataMember]
public object[] SearchSuggestions { get; set; }
}
Вот весь интерфейс:
[ServiceContract]
public interface ISuggestionService
{
[OperationContract]
[WebGet(UriTemplate = "/Search?q={searchTerms}",
BodyStyle = WebMessageBodyStyle.Bare,
ResponseFormat = WebMessageFormat.Json)]
object[] Search(string searchTerms);
}
В результате служба возвращает "Ошибка 324 (net::ERR_EMPTY_RESPONSE): неизвестная ошибка". Это единственная ошибка, которую я смог получить.
Я не могу использовать массив объектов для хранения одной строки и трех массивов? Что еще я мог бы сделать, чтобы использовать WCF для возврата правильного JSON, который соответствует этой спецификации?
РЕДАКТИРОВАТЬ: Добавлено намного больше кода
2 ответа
Вы опубликовали кучу [DataMember]. Пожалуйста, опубликуйте весь [DataContract]. Также покажите нам возвращенный JSON при возврате этого DataContract.
Контракт с данными никогда не должен включать поведение. Попробуйте следующее (у меня не было возможности протестировать его, и для этого мне нужно будет подделать данные):
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class SuggestionService : ISuggestionService
{
public SearchResults Search(string searchTerms)
{
var results = new SearchResults
{
SearchText = searchTerms,
Text = new string[10],
Urls = new string[10],
Descriptions = new string[10]
};
// Removed irrelevant ADO.NET code
int index = 0;
while (searchResultReader.Read() && index < 10)
{
results.Text[index] = searchResultReader["Company"].ToString();
results.Descriptions[index] = searchResultReader["Company"].ToString();
results.Urls[index] = "http://dev.localhost/Customers/EditCustomer.aspx?id=" +
searchResultReader["idCustomer"];
index++;
}
return results;
}
}
[DataContract]
public class SearchResults
{
[DataMember]
public string SearchText { get; set; }
[DataMember]
public string[] Text { get; set; }
[DataMember]
public string[] Descriptions { get; set; }
[DataMember]
public string[] Urls { get; set; }
}
Хорошо, я прочитал достаточно этой спецификации и спецификации JSON, чтобы убедить себя, что вам действительно нужно возвращать массив объектов, а не экземпляр класса, который содержит массив объектов. Конечно, это не совсем сработало. Вот что вам нужно:
[ServiceContract]
[ServiceKnownType(typeof(string))]
[ServiceKnownType(typeof(string[]))]
public interface ISuggestionService
{
[OperationContract]
[WebGet(UriTemplate = "/Search?q={searchTerms}",
BodyStyle = WebMessageBodyStyle.Bare,
ResponseFormat = WebMessageFormat.Json)]
object[] Search(string searchTerms);
}
Я только что попробовал, и это сработало. Вот JSON (добавлен отступ):
[
"abc",
["Company1","Company2","Company3",...],
["Company1 Description","Company2 Description","Company3 Description",...],
["http:\/\/dev.localhost\/Customers\/EditCustomer.aspx?id=1",
"http:\/\/dev.localhost\/Customers\/EditCustomer.aspx?id=2",
"http:\/\/dev.localhost\/Customers\/EditCustomer.aspx?id=3",...]
]
Это проблема, которая также на некоторое время поставила меня в тупик - есть подробное пошаговое руководство о том, как это сделать, в том числе о том, как поддерживать JSON и XML opensearch (включая сериализацию атрибутов XML) с загружаемым кодом, по адресу Msgstr " Создание лабораторий - написание провайдера предложений OpenSearch в C# с WCF ".