Невозможно сериализовать параметр типа 'System.Linq.Enumerable ...' при использовании WCF, LINQ, JSON. - PullRequest
7 голосов
/ 15 января 2010

У меня есть служба WCF. Он использует Linq-to-objects для выбора из словаря. Тип объекта прост:

public class User 
{
   public Guid Id;
   public String Name;
}

Существует коллекция из Dictionary<Guid,User>.

Я хочу использовать метод WCF OperationContract, подобный этому:

public IEnumerable<Guid> GetAllUsers()
{
    var selection = from user in list.Values
        select user.Id;
     return selection;
}

Он хорошо компилируется, но когда я запускаю его, я получаю:

Сервер обнаружил ошибку при обработке запроса. Сообщение об исключении: «Невозможно сериализовать параметр типа» System.Linq.Enumerable + WhereSelectEnumerableIterator 2[Cheeso.Samples.Webservices._2010.Jan.User,System.Guid]' (for operation 'GetAllUsers', contract 'IJsonService') because it is not the exact type 'System.Collections.Generic.IEnumerable 1 [System.Guid] 'в сигнатуре метода и отсутствует в коллекции известных типов. Чтобы сериализовать параметр, добавьте тип в коллекцию известных типов для операции, используя ServiceKnownTypeAttribute. '. Подробнее смотрите в журналах сервера.

Как я могу заставить выбор быть IEnumerable<Guid>?


EDIT
Если я изменю код, чтобы сделать это, он работает хорошо - хорошая совместимость.

public List<Guid> GetAllUsers()
{
    var selection = from user in list.Values
        select user.Id;
     return new List<Guid>(selection);
}

Есть ли способ для меня избежать создания / создания List<T>?

Ответы [ 3 ]

11 голосов
/ 20 января 2010

Нет, нужно возвращать конкретный класс из веб-службы. Сделайте возвращаемый тип List и покончите с этим.

5 голосов
/ 31 июля 2010

Вы должны использовать атрибут ServiceKnownTypes.

using System;
using System.Collections.Generic;
using System.ServiceModel;
using System.ServiceModel.Web;

namespace Test.Service
{
    [ServiceContract(Name = "Service", Namespace = "")]
    public interface IService
    {
        [OperationContract]
        [WebInvoke(
            Method = "GET",
            BodyStyle = WebMessageBodyStyle.WrappedRequest,
            RequestFormat = WebMessageFormat.Json,
            ResponseFormat = WebMessageFormat.Json)]
        [ServiceKnownType(typeof(List<EventData>))]
        IEnumerable<EventData> Method(Guid userId);
    }
}

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

1 голос
/ 15 января 2010

Вам необходимо передавать совместимые коллекции в и из ваших методов WCF.

WCF лучше всего подходит для простых типов и массивов.

Передайте массив от вашего клиента, а затем превратите его в IEnumerable в службе.

Такие вещи, как IEnumerable, не являются совместимыми, что и пытается сделать WCF.

Может быть способ обойти это с известными типами, но я всегда стремлюсь сделать свои компоненты максимально гибкими.

...