WCF 服务参考 - 在客户端获取“XmlException:名称不能以 '<' 字符开头,十六进制值 0x3C”

Posted

技术标签:

【中文标题】WCF 服务参考 - 在客户端获取“XmlException:名称不能以 \'<\' 字符开头,十六进制值 0x3C”【英文标题】:WCF Service Reference - Getting "XmlException: Name cannot begin with the '<' character, hexadecimal value 0x3C" on Client SideWCF 服务参考 - 在客户端获取“XmlException:名称不能以 '<' 字符开头,十六进制值 0x3C” 【发布时间】:2011-10-21 05:05:00 【问题描述】:

我有一个智能客户端应用程序通过 WCF 与其服务器通信。数据在客户端上创建,然后通过服务发送以进行持久化。服务器和客户端通过共享 dll 使用相同的域类,我在 Visual Studio 中使用方便的“添加服务引用”功能,它包装了 SvcUtil.exe 并生成客户端和代理类。

尝试调用服务时出现以下错误:

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: 

这特别麻烦,因为该服务一次可以运行数周而不会发生此错误,然后会突然毫无预警地再次出现。我一直无法弄清楚是什么原因造成的。当它确实发生时,我将深入研究如何修复它,并且通常不会想出比那些在实际尝试以编程方式将事物序列化为 xml 时遇到相同错误的人更多的东西。我只使用生成的客户端和代理来尝试发送这些数据。

我查看了我的解决方案的 Service References\AwesomeService 文件夹中生成的代理,没有发现任何异常。生成的文件中唯一出现的尖括号是:

*.svcinfo、Reference.svcmap、AwesomeService.disco、AwesomeService.wsdl 和 *.xsd 文件中的 xml 标记 Reference.cs 文件中通用集合的参数

我用来调用服务的代码是这样的:

using (var client = new AwesomeServiceClient())

    client.SaveAwesomeness(instanceOfAwesomeness);

这是从上面列出的调用代码上方的第一帧开始的堆栈:

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

这是什么原因造成的,我该如何预防?或者,也欢迎,我该如何进一步排除故障?

【问题讨论】:

我认为这与 .Net 序列化域类属性的方式有关。您使用的是 ISerializable 接口,还是 DataContract 属性,或者可能是一些自定义序列化? @edwin 我正在使用 Serializable 属性,但是在检查了整个域图之后,我很尴尬地说有些类缺少该属性。我会试试的。谢谢。 我收到了很多次,最后在这里尝试调试,后来才意识到这是内部捕获的第一次机会异常,对象图将成功序列化/反序列化。可能与您的特定错误无关,但仅适用于将来在调试器中遇到此问题的人(或我自己)! 【参考方案1】:

查看您的 DataTables(如果这是您用来传输数据的)。

如果 DataTable 名称为空,则 Serializer 可能会混淆并错误地序列化。

否则,如果您使用的是类型化的 [Serializable] 对象,我发现如果您使用动态属性声明,有时 Serializer 也会感到困惑,例如:

public string MyName  get; set; 

但这将是一个容易重复的错误。

【讨论】:

我没有使用 DataTables,而只是在整个服务中传送域图。但是,我确实有很多自动属性,所以如果我扩展它们,我会看看序列化程序是如何工作的。 用实例变量替换所有要支持的自动属性为我解决了这个问题。【参考方案2】:

就个人而言,我在类层次结构(不是 DataTables)的序列化方面遇到了同样的问题。

我的问题根本与自动属性无关,实际上我有很多。 我的问题是我忘记在我的一个 dll 中包含对“System.Runtime.Serialization”的引用,并且我还忘记在层次结构中的上层 [DataMember] 属性引用的某些类上添加一些属性 [DataContract]

为了跟踪我的问题,我从我的根类开始,并从层次结构中删除了一些[DataMember],直到它指出了确切的问题。这可能需要一些时间,具体取决于您的层次结构...

希望对您有所帮助! 埃里克

【讨论】:

这不是答案,因为我没有任何由我创建的 WCF 服务序列化的数据。如果我运行该方法 @JohnWashburn,抱歉耽搁了,我现在才看到你的评论。我不太了解 WCF,但我怀疑它会在发送数据之前序列化数据并在接收时反序列化数据。 在类层次结构中添加属性 [DataContract] 和 [DataMember] 对我有用。【参考方案3】:

一个类似的错误让我大吃一惊,但事实证明我的配置文件(实际上是 silverlight 的客户端配置文件)包含以下内容

   <<security mode="Transport">
       <transport clientCredentialType="None" proxyCredentialType="None" realm=""/>
       <message clientCredentialType="Certificate" algorithmSuite="Default" />
   </security>

所以有时关于额外&lt; 字符的消息应该按字面意思理解!

【讨论】:

刚刚遇到这个问题,我排了很长的队,我看不到它的结尾,而且它缺少 > 所以它可以去任何一种方式。【参考方案4】:

要么使用[Serializable] 的完整属性,要么使用[DataContract][DataMember]

以下内容给了我一个错误,可能是因为 .Net 在后台创建了一个支持变量,其中包含 XmlSerializer 不喜欢的一些字符。

[Serializable]
public class MyClass

    public int MyValue  get; private set; 
    ...

要么创建完整的属性

[Serializable]
public class MyClass

    int _myValue;
    public int MyValue
    
        get  return _myValue; 
        private set  _myValue = value; 
    
    ...

或使用DataContractDataMember 属性

[DataContract]
public class MyClass

    [DataMember]
    public int MyValue  get; private set; 
    ...

【讨论】:

【参考方案5】:

在我的例子中,其中一个类有一个属性,其数据类型是对象。像这样的:

public class BuyAddOnServiceRequest

    object site_id

将其更改为:

public class BuyAddOnServiceRequest

    string site_id

成功了!

【讨论】:

【参考方案6】:

好的,刚刚遇到了另一个场景。 我有一个 Serializable 类型用作我的 Operation Contract 方法之一的参数。

从使用中注释掉这个特定的方法让我找到了问题。在这种情况下,参数是从文件反序列化的模型,所以我只是将实现替换为 byte[] 参数并在另一端运行反序列化逻辑。

虽然不一定是所有人的答案,但对于可序列化的 Operation Contract 方法上的参数类型,您也可能会遇到此异常。我想用正确的 DataContract 属性装饰它们将有助于纠正这个问题。

【讨论】:

大多数人会发现包含一个 sn-p 代码来支持您的答案很有用。

以上是关于WCF 服务参考 - 在客户端获取“XmlException:名称不能以 '<' 字符开头,十六进制值 0x3C”的主要内容,如果未能解决你的问题,请参考以下文章

如何获取 WCF Web 服务请求的 XML SOAP 请求?

wcf客户端怎么获取自身使用的端口号?

WCF 客户端代理初始化

如何在具有 WCF 服务参考的客户端中使用 IssuedToken

重用 WCF 服务客户端

在 WCF 中获取调用者的主机名