You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 06:45:36