使用稍微复杂的方法引用 WCF 服务时获取“递归集合数据契约”

Posted

技术标签:

【中文标题】使用稍微复杂的方法引用 WCF 服务时获取“递归集合数据契约”【英文标题】:Getting "Recursive collection data contract" when referencing a WCF service with a slightly complex method 【发布时间】:2012-08-17 15:26:45 【问题描述】:

如果我在 WCF 服务中只使用简单的方法,那么一切正常。但是,如果我包含以下方法,则会出现问题:

[OperationContract]
public List<KeyValuePair<string, string>> GetAllAccounts()

    return AccountBusiness.GetAllAccounts();

从另一个项目引用服务时出现此错误:

警告 5 自定义工具警告:无法导入 wsdl:portType 详细信息:运行 WSDL 导入扩展时引发异常: System.ServiceModel.Description.DataContractSerializerMessageContractImporter 错误:类型“Newtonsoft.Json.Linq.JToken”是不支持的递归集合数据合约。考虑修改 要删除的集合“Newtonsoft.Json.Linq.JToken”的定义 对自身的引用。 错误源的 XPath://wsdl:definitions[@targetNamespace='http://tempuri.org']/wsdl:portType[@name='NodeService'] C:\inetpub\wwwroot\MyclientProject\Service References\NodeService\Reference.svcmap 1 1 MyClientNode

如果我删除上面的方法,重新编译并更新引用,那么它工作正常。但是当我添加上述方法时,我一直收到此警告。

我发现的一个建议是卸载 Visual Studio 2012 并修复 Visual Studio 2010。我不想这样做。

另一个suggested 取消选中“在所有引用的程序集中重用类型”,但这会弄乱方法签名并且不可用。

【问题讨论】:

【参考方案1】:

事实证明,错误是由于我从 NuGet 安装了一个 Microsoft Web API 包,其中包括 Json.NET。卸载后就可以正常使用了。

这可能是您的答案 - 如果没有,请查看您安装了哪些其他软件包(您不需要)并删除它们。

【讨论】:

您不必删除这些包,您现在可以在服务中使用它们:nirlevy.blogspot.co.il/2012/08/… 尼尔,这非常有用。谢谢!【参考方案2】:

安装在服务器上的 NewtonSoft.Json 库与从 NuGet 安装在客户端上的库不同。这就是服务引用无法重用它的原因。

在这种情况下,只需单击“在指定引用的程序集中重用类型”,检查除 Newtonsoft.Json 程序集之外的所有内容并重新生成。

现在生成的服务参考不会出错。

【讨论】:

【参考方案3】:

您无法直接在 WCF REST 服务中返回 JObject 或 JToken 类型,因为您会收到可怕的错误“Type 'Newtonsoft.Json.Linq.JToken' is a recursive collection data contract”。

我通过在返回 JSON 对象之前将它们序列化为 Stream 类型来解决此问题...

[WebInvoke(Method = "GET",
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.WrappedResponse,
UriTemplate = "/api/myGetRequest")]
public Stream myFunction(string x, string y)
 
  WebOperationContext webcontext = WebOperationContext.Current;
  webcontext.OutgoingResponse.Headers[HttpResponseHeader.ContentType] = "application/json";

  string json = JsonConvert.SerializeObject(myJsonObject, Newtonsoft.Json.Formatting.Indented);`

  return new MemoryStream(Encoding.UTF8.GetBytes(json ?? ""));

【讨论】:

以上是关于使用稍微复杂的方法引用 WCF 服务时获取“递归集合数据契约”的主要内容,如果未能解决你的问题,请参考以下文章

将 WCF 服务添加为 Web 引用和服务引用时的不同代理类

WCF REST - 使用复杂类型的“获取”

无法从本地机器调用 WCF 服务

无法从本地机器调用 WCF 服务

无法在 WCF Rest 中获取未定义或空引用的属性“appendChild”

在类库中使用 WCF 服务时出错