WCF服务含XML非法字符时,如何使其始终输出合法XML?
解决WCF服务输出含非法XML字符的问题
针对WCF服务输出包含XML非法控制字符(如)的问题,有几种可靠的解决方案,按实现复杂度从低到高排列:
1. 在数据契约层直接清洗非法字符
这是最直接的方案,在数据进入序列化流程前就完成字符过滤,确保输出的XML完全符合标准。
首先实现一个静态工具方法,用于移除XML 1.0规范中不允许的控制字符(保留制表符\t、换行\n、回车\r):
public static class XmlUtils { public static string RemoveInvalidXmlChars(string input) { if (string.IsNullOrWhiteSpace(input)) return input; // 匹配XML 1.0中禁止的控制字符范围 var invalidCharsRegex = new Regex(@"[\x00-\x08\x0B\x0C\x0E-\x1F]"); return invalidCharsRegex.Replace(input, string.Empty); } }
然后在你的DataContract类中,通过属性的get/set方法调用这个工具方法:
[DataContract] public class YourDataContract { private string _content; [DataMember] public string Content { get => _content; set => _content = XmlUtils.RemoveInvalidXmlChars(value); } }
2. 自定义数据契约代理(IDataContractSurrogate)
如果不想修改现有DataContract的属性逻辑,可以通过自定义代理在序列化阶段统一处理所有字符串类型的成员:
实现IDataContractSurrogate接口,重写GetObjectToSerialize方法来清洗字符串:
public class XmlCleaningSurrogate : IDataContractSurrogate { public object GetObjectToSerialize(object obj, Type targetType) { if (obj is string str) return XmlUtils.RemoveInvalidXmlChars(str); return obj; } // 其他接口方法默认实现即可 public Type GetDataContractType(Type type) => type; public object GetDeserializedObject(object obj, Type targetType) => obj; public object GetCustomDataToExport(Type clrType, Type dataContractType) => null; public object GetCustomDataToExport(MemberInfo memberInfo, Type dataContractType) => null; public void GetKnownCustomDataTypes(Collection<Type> customDataTypes) { } public Type GetReferencedTypeOnImport(string typeName, string typeNamespace, object customData) => null; public CodeTypeDeclaration ProcessImportedType(CodeTypeDeclaration typeDeclaration, CodeCompileUnit compileUnit) => typeDeclaration; }
然后在WCF服务的配置/初始化代码中,为DataContractSerializer添加这个代理:
// 在服务宿主初始化时添加行为 var host = new ServiceHost(typeof(YourService)); foreach (var endpoint in host.Description.Endpoints) { foreach (var operation in endpoint.Contract.Operations) { var serializerBehavior = operation.Behaviors.Find<DataContractSerializerOperationBehavior>(); if (serializerBehavior != null) { serializerBehavior.DataContractSurrogate = new XmlCleaningSurrogate(); } } } host.Open();
3. 自定义XML消息格式化器
如果需要更底层的控制,可以实现IMessageFormatter,在消息序列化的最后阶段处理输出内容。不过这个方案复杂度较高,仅在前面两种方案无法满足需求时考虑。
注意:不要尝试设置
XmlWriterSettings.CheckCharacters = false,这会让WCF跳过字符检查直接输出非法字符,导致生成的XML不符合标准,无法被正常解析。
内容的提问来源于stack exchange,提问作者Banshee
相关产品推荐
相关产品推荐

