Сериализация массива объектов в JSON в WCF для соответствия OpenSearch - PullRequest
4 голосов
/ 16 июля 2009

Я пытаюсь написать службу предложений 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 ]

5 голосов
/ 16 июля 2009

Вы опубликовали кучу [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",...]
]
2 голосов
/ 19 августа 2009

Это проблема, которая также на некоторое время поставила меня в тупик - есть полное сквозное пошаговое руководство о том, как это сделать, в том числе о том, как поддерживать JSON и XML opensearch (включая сериализацию атрибутов XML), с возможностью загрузки код в " Building Labs - Написание поставщика предложений OpenSearch в C # с WCF ".

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...