Служба WCF, возвращающая JSON с анонимным объектом - PullRequest
4 голосов
/ 01 декабря 2011

Для простого API, который я строю, я использую несколько методов.Прежде всего, это не первый мой API, который я создаю, но это первый случай, когда у меня есть комбинация WCF, json и анонимных объектов.

Я получил следующий интерфейс для WCF API:

[ServiceContract]
public interface IAPI
{
    [OperationContract]
    [WebInvoke(Method = "POST",
                 BodyStyle = WebMessageBodyStyle.WrappedRequest,
                 ResponseFormat = WebMessageFormat.Json,
                 RequestFormat = WebMessageFormat.Json)]
    ServiceResponse Authenticate(string username, string hashedPassword);

    [OperationContract]
    [WebInvoke(Method = "POST",
                 BodyStyle = WebMessageBodyStyle.WrappedRequest,
                 ResponseFormat = WebMessageFormat.Json,
                 RequestFormat = WebMessageFormat.Json)]
    ServiceResponse GetProducts();
}

Все довольно просто, всего 2 метода, которые я хочу использовать.Класс ServiceResponse, который вы видите, также очень прост, но я думаю, что он вызывает проблемы:

[DataContract]
public class ServiceResponse
{
    [DataMember]
    public ResponseCode Status { get; set; }

    [DataMember]
    public object Value { get; set; }
}

Я создал этот класс, поэтому я всегда могу отправить Status (Simple int enum) и объект,например, строка или список объектов.

Я создал небольшой скрипт, используя jQuery для тестирования моего сервиса, и метод Authenticate работает так, как должен, но этот метод возвращает объект ServiceResponse, спросто 0 в поле Status.Поле Value здесь оставлено пустым.

Метод GetProducts - это тот, где он становится сложным, массив анонимных объектов, таких как:

public ServiceResponse GetProducts()
{
       DataClassesDataContext db = new DataClassesDataContext();
       var results = from p in db.Products
                     where p.UserID == 1
                     select new
                     {
                         ID = p.ID,
                         Name = p.DecryptedName
                     };

        return ServiceResponse.OK(results.ToArray());
}

Я используюздесь объект анонимного типа, потому что я не хочу создавать прокси-классы для всех классов, которые я хочу использовать в API.

Когда я пробую этот код с помощью моего простого скрипта jQuery, FireBug говорит мне, что мойзапрос был прерван.Я думаю, это из-за ошибки 500 или что-то.Когда я ставлю точку останова в своем методе GetProducts, он срабатывает 7 раз, прежде чем Firefox сообщает, что он прерван и скрипт полностью запущен.

Вот сценарий jQuery, который я использую для тестирования моей службы WCF:

$.ajax({
    type: "POST",
    contentType: "application/json; charset=utf-8",
    url: "/Handlers/API.svc/GetProducts",
    data: '{}',
    dataType: "json",
    success: function (response) {
        var test = inspect(response, 5);
        $("#output").html(test);
    },
    error: function (message) {
        $("#output").html(inspect(message, 5));
    }
});

Метод inspect, который вы видите там, это всего лишь небольшой JS-скрипт, который показывает мне содержимое объекта.

Я пробовал следующие вещи, чтобы заставить его двигаться:

  • Заменить анонимные объекты объектами типа Product, но это не удалось аналогичным образом
  • Вернуть List<T> вместо массива, но там тоже не повезло.
  • Возврат без присваивания свойству Value, это сработало
  • Изменение свойства Value на тип dynamic, также не удалось

Мне бы понравилось, если бы я мог использовать WCF для возврата какого-либо массива анонимных объектов, потому что это спасло бы меня от создания 30+ прокси-классов.

NOTE : класс Productкласс, сгенерированный LINQ.Я использую C # 4.0 для этого.

Ответы [ 2 ]

2 голосов
/ 01 декабря 2011

Возможно, я ошибаюсь, но я считаю, что WCF довольно строг и не позволит вам вернуть объект так, как вы пытаетесь.Если вы знаете, что данные будут представлять собой массив каждый раз, вы можете изменить свое определение, чтобы отразить это (но, похоже, это не сработает в вашем случае).В противном случае вы можете захотеть изменить подпись на простую строку и сериализовать данные в JSON, а затем вернуть их.

0 голосов
/ 08 марта 2017

Краткий ответ: Вы не можете.Вместо этого вы должны использовать веб-службы или, как вы сказали, использовать прокси-класс.

...