Today I was taught an immensely important lesson by WCF. It actually has nothing
to do with WCF except that because of the size of the schema I’m working with that
is where I encountered it.
I do a lot of work in the healthcare industry, and that industry, by government mandate,
works with a message format called the 837 (properly the X12 4010A1 837 either I,
P or D). The 837 has three flavors, and is absolutely huge. I was crafting
a service which had to accept an XML representation of this data. How did I create
the XML? BizTalk Server 2006 R2’s new HIPAA support of course. When
I made the call to service from my unit tests I first received a Fault indicating
that exception details could not be returned because of configuration. No problem,
obviously I’ve seen this before and so I added the following to my app.Config for
the Host executable:
< behaviors >
< serviceBehaviors >
< behavior name ="EnableDebugging" >
< serviceDebug includeExceptionDetailInFaults ="true" />
</ behavior >
</ serviceBehaviors >
</ behaviors >
Now that I’ve enabled debugging, surely now I’ll see some sort of clear reason by
this occurred. Nope! I was presented with the following:
TheCompany.Services.Tests.ClaimsService.GetListOfClaimsByStatus : System.ServiceModel.FaultException`1[System.ServiceModel.ExceptionDetail]
: Error in deserializing body of request message for operation ‘GetClaimListByStatus’.
Well isn’t that terribly useful. Fortunately, this did give me the single most
important piece of information “deserializing”. So off I go to Google my brain,
because I’d
written a post before on how to debug the XmlSerializer (and I was using the XmlSerializer
in this case because the DataContractSerializer could not work with my schema).
As that post will tell you, there is a switch that can be set in the app.Config which
will enable you to debug the code generated by the XmlSerializer. So now we
add the following to my app.Config:
< system.diagnostics >
< switches >
< add name ="XmlSerialization.Compilation" value ="1" />
</ switches >
</ system.diagnostics >
And we follow that by running the unit tests again, that results in something that
is actively useful:
For those reading along at home and wanting the full text that says:
The maximum nametable character count quota (10000) has been exceeded while reading
XML data. The nametable is a data structure used to store strings encountered during
XML processing – long XML documents with non-repeating element names, attribute names
and attribute values may trigger this quota. This quota may be increased by changing
the MaxNameTableCharCount property on the XmlDictionaryReaderQuotas object used when
creating the XML reader.
Now that is useful, it tells me exactly how to correct the problem and the size of
the quota currently. The only problem is that I didn’t create this XmlReader
object, I didn’t even create the XmlSerializer which created this XmlReader.
The only thing which I create was a ServiceHost, how can I change that setting?
Enter Google again.
As it happens, Windows Communication Foundation does include an ability to override
that value, it is stored in the Binding Configuration in your … you guessed it …
app.Config! Add the following snippet (assuming you’re using Basic Http Binding
(it exists for all bindings though) and you’ll be good to go:
< bindings >
< basicHttpBinding >
< binding name ="BasicHttpBinding" >
< readerQuotas maxNameTableCharCount ="100000" />
</ binding >
</ basicHttpBinding >
</ bindings >
Now, surely I’m done, and things will work. Actually, no it took mea few
times to find a value that would work for that quota. Once I did though I finally
hit my breakpoint inside the service and was able to send back a response, where upon
I got this message:
TheCompany.Services.Tests.ClaimsService.GetListOfClaimsByStatus : System.ServiceModel.CommunicationException
: Error in deserializing body of reply message for operation ‘GetClaimListByStatus’.
—-> System.InvalidOperationException : There is an error in XML document
(1, 252).
—-> System.Xml.XmlException : The maximum nametable character count quota
(10000) has been exceeded while reading XML data. The nametable is a data structure
used to store strings encountered during XML processing – long XML documents with
non-repeating element names, attribute names and attribute values may trigger this
quota. This quota may be increased by changing the MaxNameTableCharCount property
on the XmlDictionaryReaderQuotas object used when creating the XML reader. Line 1,
position 252.
At least when the error occurs on the client side you get the full details to start
with! Make the same modification above to your configuration on the client side
and you’re good to go.