代码之家  ›  专栏  ›  技术社区  ›  Cheeso

使用wcf、linq、json时,无法序列化类型为“System.Linq.Enumerable…”的参数

  •  7
  • Cheeso  · 技术社区  · 15 年前

    我有WCF服务。它使用Linq to对象从字典中进行选择。对象类型很简单:

    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+WhereSelecteEnumerableIterator类型的参数 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> ?


    编辑
    如果我修改代码来做到这一点,它会很好地工作——良好的互操作性。

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

    我有没有办法避免 List<T> ?

    3 回复  |  直到 14 年前
        1
  •  11
  •   Cheeso    15 年前

    不,必须从Web服务返回具体类。制作返回类型列表并完成它。

        2
  •  4
  •   A-Dubb    14 年前

    必须使用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);
        }
    }
    

    基本上,你需要知道你返回的具体类型。很简单。

        3
  •  1
  •   Tad Donaghe    15 年前

    您需要在WCF方法之间传递可互操作的集合。

    对于简单的类型和数组,WCF发挥得最好。

    从客户端传入一个数组,然后将其转换为服务中的IEnumerable。

    像IEnumerable这样的东西是不可互操作的,这正是WCF试图做到的。

    可能有一种方法可以用已知的类型绕过它,但我总是努力使我的组件尽可能灵活。