Returning a custom class in WCF
I created WCF service that returns a custom object called XmlElementTreeNode. This is what the object looks like:
[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() { }
}
I am able to successfully create a heirarchy of these nodes with this method:
[OperationContract]
public XmlElementTreeNode GetTreeView(string initialSchemaUri)
{
Uri uri = new Uri(initialSchemaUri, UriKind.Absolute);
XPathSorter sorter = new XPathSorter(uri);
XmlElementTreeNode theNode = sorter.rootTreeNode;
return theNode;
}
But the error I get back is:
CommunicationException was unhandled by user code
The remote server returned an error: NotFound.
at this method in Reference.cs:
public SilverlightApplication.SchemaServiceReference.XmlElementTreeNode EndGetTreeView(System.IAsyncResult result)
{
obj开发者_如何学运维ect[] _args = new object[0];
SilverlightApplication.SchemaServiceReference.XmlElementTreeNode _result = ((SilverlightApplication.SchemaServiceReference.XmlElementTreeNode)(base.EndInvoke("GetTreeView", _args, result)));
return _result;
}
I rewrote the service to return theNode.Name
and theNode.Attributes
instead. Both of those worked. I also rewrote the service to return theNode.Children
and I get the same exact error.
So, when I get this error, I never reach this code in Silverlight, because the service did not "finish."
void service_GetTreeViewCompleted(object sender, GetTreeViewCompletedEventArgs e)
{
XmlElementTreeNode rootNode = e.Result;
}
However, I found this interesting. I changed return theNode
to return theNode.Children[0]
. So, I still am returning an XmlElementTreeNode object to Silverlight. When I did this, I was able to reach the service_GetTreeViewCompleted
method and access my tree of nodes (although only starting from the first child of the root node). I think it's strange that this worked, but not the "root" node (the original theNode
variable).
Anyone have any ideas how I can return my theNode
variable? I'm completely new to WCF, so maybe there is some other way to go about returning my complex custom object properly that I am not aware of.
Update 1
My XmlElementTreeNode
object represents an xml element as defined by an xsd document. The generated heiarchy of XmlElementTreeNodes
represent all the possible elements that could be created in an XML file thati validated against the XSD uri being passed into my service. It just so happens that the first element of theNode.Children
represents only a small tree of nodes. However, I tried to return theNode.Children[1]
, which has thousands of sub-nodes, and I get the same error. So, I think the problem is that the size of the entire theNode
object is simply too big.
I tried editing my binding as follows in 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>
But, even with those huge values, I get the same error.
The "NotFound" error is a big issue in Silverlight because it essentially means that "something went wrong" - by default all non-200 responses from the service are translated into a 404 (Not Found) by the SL networking layer, and no further information is given to the program. A few things you can do:
- Look at a network capture tool (such as Fiddler) to see the exact response that the server is returning to the client.
- If the response is something like 500 (Internal Server Error), enable tracing on the server side and the trace should contain an exception which explains the error.
There are some documentations about debugging WCF services in SL. There's a good video (25 minutes long) at http://blogs.msdn.com/b/silverlightws/archive/2010/09/23/debugging-wcf-services-in-silverlight.aspx, and there's a MSDN page at http://msdn.microsoft.com/en-us/library/cc197938(v=VS.95).aspx with some good information as well.
As expected, the problem is that my returned object is too big. I found out that I needed to add the following line to my Web.config:
<dataContractSerializer maxItemsInObjectGraph="2147483647"/>
In context with the rest of the 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>
...
精彩评论