【问题标题】:Returning a custom class in WCF在 WCF 中返回自定义类
【发布时间】:2011-06-07 17:23:50
【问题描述】:

我创建了 WCF 服务,该服务返回一个名为 XmlElementTreeNode 的自定义对象。这是对象的样子:

[DataContract]
public class XmlElementTreeNode
{
    [DataMember]
    public string Name { get; set; }

    [DataMember]
    public List<string> Attributes { get; set; }

    [DataMember]
    public List<XmlElementTreeNode> Children { get; set; }

    public XmlElementTreeNode() { }
}

我能够使用这种方法成功地创建这些节点的层次结构:

[OperationContract]
public XmlElementTreeNode GetTreeView(string initialSchemaUri)
{
    Uri uri = new Uri(initialSchemaUri, UriKind.Absolute);
    XPathSorter sorter = new XPathSorter(uri);
    XmlElementTreeNode theNode = sorter.rootTreeNode;
    return theNode;
}

但我得到的错误是:

CommunicationException was unhandled by user code
The remote server returned an error: NotFound.

在 Reference.cs 中的这个方法:

public SilverlightApplication.SchemaServiceReference.XmlElementTreeNode EndGetTreeView(System.IAsyncResult result)
{
    object[] _args = new object[0];
    SilverlightApplication.SchemaServiceReference.XmlElementTreeNode _result = ((SilverlightApplication.SchemaServiceReference.XmlElementTreeNode)(base.EndInvoke("GetTreeView", _args, result)));
    return _result;
}

我重写了服务以返回 theNode.NametheNode.Attributes。这两个都有效。我还重写了服务以返回theNode.Children,我得到了同样的错误。

因此,当我收到此错误时,我从未在 Silverlight 中找到此代码,因为服务没有“完成”。

void service_GetTreeViewCompleted(object sender, GetTreeViewCompletedEventArgs e)
{
    XmlElementTreeNode rootNode = e.Result;
}

但是,我发现这很有趣。我将return theNode 更改为return theNode.Children[0]。所以,我仍然将 XmlElementTreeNode 对象返回给 Silverlight。当我这样做时,我能够访问service_GetTreeViewCompleted 方法并访问我的节点树(尽管仅从根节点的第一个子节点开始)。我认为这很奇怪,但不是“根”节点(原始的theNode 变量)。

有人知道如何返回我的theNode 变量吗?我对 WCF 完全陌生,所以也许还有其他方法可以正确返回我不知道的复杂自定义对象。

更新 1

我的XmlElementTreeNode 对象表示由 xsd 文档定义的 xml 元素。生成的XmlElementTreeNodes 层次结构代表了可以在 XML 文件中创建的所有可能元素,这些元素已针对传递到我的服务的 XSD uri 进行了验证。碰巧theNode.Children 的第一个元素只代表一棵小节点树。但是,我尝试返回具有数千个子节点的theNode.Children[1],我得到了同样的错误。所以,我认为问题在于整个theNode 对象的大小太大了。

我尝试在 Web.config 中按如下方式编辑我的绑定:

    <binding name="SilverlightApplication.Web.SchemaService.customBinding0">
      <textMessageEncoding>
        <readerQuotas maxDepth="2147483647"
          maxStringContentLength="2147483647"
          maxArrayLength="2147483647"
          maxBytesPerRead="2147483647"
          maxNameTableCharCount="2147483647" />
      </textMessageEncoding>
      <httpTransport maxBufferSize="2147483647" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647" />
      <binaryMessageEncoding maxReadPoolSize="2147483647" maxSessionSize="2147483647" maxWritePoolSize="2147483647" />
    </binding>

但是,即使有这些巨大的值,我也会遇到同样的错误。

【问题讨论】:

    标签: c# silverlight wcf custom-object


    【解决方案1】:

    “NotFound”错误是 Silverlight 中的一个大问题,因为它本质上意味着“出了点问题” - 默认情况下,来自服务的所有非 200 响应都会被 SL 网络层转换为 404(未找到),并且没有向该计划提供进一步的信息。您可以做的几件事:

    • 查看网络捕获工具(例如Fiddler)以查看服务器返回给客户端的确切响应。
    • 如果响应类似于 500(内部服务器错误),则在服务器端 enable tracing 并且跟踪应包含解释错误的异常。

    有一些关于在 SL 中调试 WCF 服务的文档。 http://blogs.msdn.com/b/silverlightws/archive/2010/09/23/debugging-wcf-services-in-silverlight.aspx 有一个很好的视频(25 分钟长),http://msdn.microsoft.com/en-us/library/cc197938(v=VS.95).aspx 有一个 MSDN 页面,其中包含一些很好的信息。

    【讨论】:

    • 使用 Fiddler,我的服务得到了这样的响应:“ReadResponse() 失败:服务器没有针对这个请求返回响应。”我还将考虑启用跟踪。
    • 视频很有帮助。但是,我在那个视频上尝试了所有东西,只有一个案例我有任何类型的不同调试结果。当我在 ServicesReferences.ClientConfig 中更新我的服务以使用相对路径(../SchemaService.svc 而不是 http://localhost:12345/SchemaService.svc)时,我返回 TimeoutException 未被用户代码处理远程服务器返回错误:Visual Studio 中未找到。但在 Fiddler 或 ViewDetail -> InnerException / StackTrace 等中没有出现任何额外内容。
    • “ReadResponse() 失败:服务器没有返回响应” - 请求是否真正到达服务器?至于使用localhost...时没有显示任何内容,IIRC fiddler 不会捕获发送到 localhost 的请求,您需要将其发送到机器名称(并打开 SL 页面使用机器名而不是 localhost,以防止跨域问题)
    • 要尝试的另一件事:创建一个非 Silverlight(即“正常”)WCF 客户端来与此服务通信,这可能有助于消除一些特定于 SL 的通信问题。跨度>
    【解决方案2】:

    不出所料,问题是我返回的对象太大了。我发现我需要将以下行添加到我的 Web.config:

    <dataContractSerializer maxItemsInObjectGraph="2147483647"/>
    

    在与 Web.config 其余部分的上下文中:

    <configuration>
      <system.web>
        <compilation debug="true" targetFramework="4.0">
          <assemblies>
            <add assembly="System.Data.Entity, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
          </assemblies>
        </compilation>
      </system.web>
      <system.serviceModel>
        <behaviors>
          <serviceBehaviors>
            <behavior name="">
              <dataContractSerializer maxItemsInObjectGraph="2147483647"/>
              <serviceMetadata httpGetEnabled="true" />
              <serviceDebug includeExceptionDetailInFaults="true" />
            </behavior>
          </serviceBehaviors>
        </behaviors>
       ...
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-07-15
      • 2023-03-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多