问题
I have a smart client application communicating with its server via WCF. Data is created on the client and then sent over the service to be persisted. The server and client use the same domain classes via a shared dll and I'm using the handy "Add Service Reference" functionality in Visual Studio that wraps SvcUtil.exe and generates the client and proxy classes.
I get the following error when trying to call the service:
System.Xml.XmlException occurred
Message=Name cannot begin with the '<' character, hexadecimal value 0x3C.
Source=System.Xml
LineNumber=0
LinePosition=1
StackTrace:
at System.Xml.XmlConvert.VerifyNCName(String name, ExceptionType exceptionType)
InnerException:
This is particularly troublesome because the service will work for weeks at a time without this error occurring and then suddenly and without warning it will appear again. I haven't been able to figure out what causes it at all. When it does happen, I will do a deep dive into researching how to fix it and usually don't come up with anything more than people who have experienced the same error while actually trying to serialize things to xml programmatically. I am using nothing but the generated client and proxies to try and send this data.
I have looked into the generated proxies in the Service References\AwesomeService
folder of my solution and see nothing that looks out of the ordinary. The only occurrences of angle brackets in the generated files are:
- xml tags in the *.svcinfo, Reference.svcmap, AwesomeService.disco, AwesomeService.wsdl and *.xsd files
- arguments to generic collections in the Reference.cs file
The code I'm using to call the service is such:
using (var client = new AwesomeServiceClient())
{
client.SaveAwesomeness(instanceOfAwesomeness);
}
This is the stack beggining with the first frame above the calling code listed above:
System.Xml.dll!System.Xml.XmlConvert.VerifyNCName(string name, System.Xml.ExceptionType exceptionType) + 0xb5 bytes
System.Runtime.Serialization.dll!System.Runtime.Serialization.DataContract.IsValidNCName(string name) + 0x27 bytes
System.Runtime.Serialization.dll!System.Runtime.Serialization.DataContract.EncodeLocalName(string localName) + 0x1d bytes
System.Runtime.Serialization.dll!System.Runtime.Serialization.ClassDataContract.ClassDataContractCriticalHelper.ImportDataMembers() + 0x2e1 bytes
System.Runtime.Serialization.dll!System.Runtime.Serialization.ClassDataContract.ClassDataContractCriticalHelper.ClassDataContractCriticalHelper(System.Type type) + 0x10d bytes
System.Runtime.Serialization.dll!System.Runtime.Serialization.DataContract.DataContractCriticalHelper.CreateDataContract(int id, System.RuntimeTypeHandle typeHandle, System.Type type) + 0x198 bytes
System.Runtime.Serialization.dll!System.Runtime.Serialization.DataContract.DataContractCriticalHelper.GetDataContractSkipValidation(int id, System.RuntimeTypeHandle typeHandle, System.Type type) + 0x57 bytes
System.Runtime.Serialization.dll!System.Runtime.Serialization.XmlObjectSerializerContext.GetDataContract(int id, System.RuntimeTypeHandle typeHandle) + 0x37 bytes
System.Runtime.Serialization.dll!System.Runtime.Serialization.XmlObjectSerializerWriteContext.InternalSerialize(System.Runtime.Serialization.XmlWriterDelegator xmlWriter, object obj, bool isDeclaredType, bool writeXsiType, int declaredTypeID, System.RuntimeTypeHandle declaredTypeHandle) + 0x49 bytes
[Lightweight Function]
System.Runtime.Serialization.dll!System.Runtime.Serialization.ClassDataContract.WriteXmlValue(System.Runtime.Serialization.XmlWriterDelegator xmlWriter, object obj, System.Runtime.Serialization.XmlObjectSerializerWriteContext context) + 0x25 bytes
System.Runtime.Serialization.dll!System.Runtime.Serialization.XmlObjectSerializerWriteContext.WriteDataContractValue(System.Runtime.Serialization.DataContract dataContract, System.Runtime.Serialization.XmlWriterDelegator xmlWriter, object obj, System.RuntimeTypeHandle declaredTypeHandle) + 0x18 bytes
System.Runtime.Serialization.dll!System.Runtime.Serialization.XmlObjectSerializerWriteContext.SerializeWithoutXsiType(System.Runtime.Serialization.DataContract dataContract, System.Runtime.Serialization.XmlWriterDelegator xmlWriter, object obj, System.RuntimeTypeHandle declaredTypeHandle) + 0x49 bytes
System.Runtime.Serialization.dll!System.Runtime.Serialization.DataContractSerializer.InternalWriteObjectContent(System.Runtime.Serialization.XmlWriterDelegator writer, object graph, System.Runtime.Serialization.DataContractResolver dataContractResolver) + 0xdf bytes
System.Runtime.Serialization.dll!System.Runtime.Serialization.DataContractSerializer.InternalWriteObject(System.Runtime.Serialization.XmlWriterDelegator writer, object graph, System.Runtime.Serialization.DataContractResolver dataContractResolver) + 0x26 bytes
System.Runtime.Serialization.dll!System.Runtime.Serialization.XmlObjectSerializer.WriteObjectHandleExceptions(System.Runtime.Serialization.XmlWriterDelegator writer, object graph, System.Runtime.Serialization.DataContractResolver dataContractResolver) + 0x60 bytes
System.Runtime.Serialization.dll!System.Runtime.Serialization.XmlObjectSerializer.WriteObject(System.Xml.XmlDictionaryWriter writer, object graph) + 0x2d bytes
System.ServiceModel.dll!System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.SerializeParameterPart(System.Xml.XmlDictionaryWriter writer, System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.PartInfo part, object graph) + 0x38 bytes
System.ServiceModel.dll!System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.SerializeParameter(System.Xml.XmlDictionaryWriter writer, System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.PartInfo part, object graph) + 0xbe bytes
System.ServiceModel.dll!System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.SerializeParameters(System.Xml.XmlDictionaryWriter writer, System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.PartInfo[] parts, object[] parameters) + 0x3e bytes
System.ServiceModel.dll!System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.SerializeBody(System.Xml.XmlDictionaryWriter writer, System.ServiceModel.Channels.MessageVersion version, string action, System.ServiceModel.Description.MessageDescription messageDescription, object returnValue, object[] parameters, bool isRequest) + 0x68 bytes
System.ServiceModel.dll!System.ServiceModel.Dispatcher.OperationFormatter.SerializeBodyContents(System.Xml.XmlDictionaryWriter writer, System.ServiceModel.Channels.MessageVersion version, object[] parameters, object returnValue, bool isRequest) + 0x7b bytes
System.ServiceModel.dll!System.ServiceModel.Dispatcher.OperationFormatter.OperationFormatterMessage.OperationFormatterBodyWriter.OnWriteBodyContents(System.Xml.XmlDictionaryWriter writer) + 0x4f bytes
System.ServiceModel.dll!System.ServiceModel.Channels.BodyWriter.WriteBodyContents(System.Xml.XmlDictionaryWriter writer) + 0xf8 bytes
System.ServiceModel.dll!System.ServiceModel.Channels.BodyWriterMessage.OnBodyToString(System.Xml.XmlDictionaryWriter writer) + 0x1f bytes
System.ServiceModel.dll!System.ServiceModel.Channels.Message.ToString(System.Xml.XmlDictionaryWriter writer) + 0xaa bytes
System.ServiceModel.dll!System.ServiceModel.Diagnostics.MessageLogTraceRecord.WriteTo(System.Xml.XmlWriter writer) + 0x166 bytes
System.ServiceModel.dll!System.ServiceModel.Diagnostics.MessageLogger.LogInternal(System.ServiceModel.Diagnostics.MessageLogTraceRecord record) + 0x77 bytes
System.ServiceModel.dll!System.ServiceModel.Diagnostics.MessageLogger.LogMessageImpl(ref System.ServiceModel.Channels.Message message, System.Xml.XmlReader reader, System.ServiceModel.Diagnostics.MessageLoggingSource source) + 0x104 bytes
System.ServiceModel.dll!System.ServiceModel.Diagnostics.MessageLogger.LogMessage(ref System.ServiceModel.Channels.Message message, System.Xml.XmlReader reader, System.ServiceModel.Diagnostics.MessageLoggingSource source) + 0x3a bytes
System.ServiceModel.dll!System.ServiceModel.Channels.ServiceChannel.PrepareCall(System.ServiceModel.Dispatcher.ProxyOperationRuntime operation, bool oneway, ref System.ServiceModel.Dispatcher.ProxyRpc rpc) + 0x436 bytes
System.ServiceModel.dll!System.ServiceModel.Channels.ServiceChannel.Call(string action, bool oneway, System.ServiceModel.Dispatcher.ProxyOperationRuntime operation, object[] ins, object[] outs, System.TimeSpan timeout) + 0x12b bytes
System.ServiceModel.dll!System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(System.Runtime.Remoting.Messaging.IMethodCallMessage methodCall, System.ServiceModel.Dispatcher.ProxyOperationRuntime operation) + 0x64 bytes
System.ServiceModel.dll!System.ServiceModel.Channels.ServiceChannelProxy.Invoke(System.Runtime.Remoting.Messaging.IMessage message) + 0x6a bytes
mscorlib.dll!System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(ref System.Runtime.Remoting.Proxies.MessageData msgData, int type) + 0xee bytes
What causes this and how do I prevent it? Or, also welcomed, how do I go about troubleshooting this further?
回答1:
Have a look at your DataTables (if that's what you are using to transport data).
If the DataTable name is empty, then the Serializer might get confused and serialise things incorrectly.
Otherwise, if you are using typed, [Serializable] objects, I have found that sometimes the Serializer also gets confused if you use dynamic property declarations, eg:
public string MyName { get; set; }
But this would be a easily repeatable error.
回答2:
Personnally, I got the same problem with serialization of class hierarchy (not DataTables).
My problem was not related to automatic property at all, in fact I have many.
My problem was that I forgot to include reference to "System.Runtime.Serialization
" in one of my dll and I also forgot to add some attributes [DataContract]
on some classes referenced by upper [DataMember]
attributes up in the hierarchy.
To track my problem I started from my root class and removed some [DataMember]
down the hierarchy until it pointed out the exact problem. It could takes some times depending on your hierarchy levels...
Hope it helps! Eric
回答3:
A similar error tripped me up, but it turned out my config file (actually a clientconfig file for silverlight) contained the following
<<security mode="Transport">
<transport clientCredentialType="None" proxyCredentialType="None" realm=""/>
<message clientCredentialType="Certificate" algorithmSuite="Default" />
</security>
So sometimes messages about extra <
characters should be taken literally!
回答4:
Either use full properties with [Serializable]
, or use [DataContract]
and [DataMember]
.
The following was giving me an error, probably because .Net was creating a backing variable under the hood, with some character that the XmlSerializer
didn't like.
[Serializable]
public class MyClass
{
public int MyValue { get; private set; }
...
}
Either create full properties
[Serializable]
public class MyClass
{
int _myValue;
public int MyValue
{
get { return _myValue; }
private set { _myValue = value; }
}
...
}
Or use the DataContract
and DataMember
attributes
[DataContract]
public class MyClass
{
[DataMember]
public int MyValue { get; private set; }
...
}
回答5:
In my case, one of the classes had a property, whose datatype was object. Something like this:
public class BuyAddOnServiceRequest
{
object site_id
}
after changing this to:
public class BuyAddOnServiceRequest
{
string site_id
}
it worked!
回答6:
Ok just came across another scenario on this one. I had a Serializable type used as a parameter for one of my Operation Contract methods.
Commenting out this specific method from use allowed me to find the issue. In this case, the parameter was a model deserialized from a file, so I just replaced the implementation with a parameter of byte[] and ran deserialization logic at the other end.
While not necessarily an answer for all, in the case of parameter types on your Operation Contract methods that are Serializable, you may run into this exception also. I would imagine decorating them with correct DataContract attributes would assist in rectifying this problem.
来源:https://stackoverflow.com/questions/6962567/wcf-service-reference-getting-xmlexception-name-cannot-begin-with-the-ch