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

.NET 7迁移WCF客户端时CreateMessage因转义ASCII字符失败

解决.NET 7 WCF客户端中0x07(响铃符)的字符检查异常问题

问题背景

将WCF客户端从.NET Framework迁移到.NET 7后,序列化包含ASCII 0x07分隔符的对象时,原本在.NET Framework中该字符会自动转义为,但在.NET 7中调用Message.ToString()时抛出System.ArgumentException: '\a', hexadecimal value 0x07, is an invalid character异常。直接使用XmlReader/XmlWriter时可通过CheckCharacters = false跳过检查,但WCF Message对象没有直接配置该属性的入口。

解决方案

方案1:自定义客户端消息格式化器(推荐)

通过实现IClientMessageFormatter扩展WCF的序列化逻辑,手动配置XmlWriter关闭字符检查:

public class CustomClientFormatter : IClientMessageFormatter
{
    private readonly IClientMessageFormatter _originalFormatter;

    public CustomClientFormatter(IClientMessageFormatter originalFormatter)
    {
        _originalFormatter = originalFormatter;
    }

    public Message SerializeRequest(MessageVersion messageVersion, object[] parameters)
    {
        var originalMessage = _originalFormatter.SerializeRequest(messageVersion, parameters);
        var bufferedCopy = originalMessage.CreateBufferedCopy(int.MaxValue);
        var clonedMessage = bufferedCopy.CreateMessage();

        // 创建新消息,使用关闭字符检查的XmlWriter写入内容
        var newMessage = Message.CreateMessage(messageVersion, clonedMessage.Headers.Action);
        var writerSettings = new XmlWriterSettings { CheckCharacters = false };
        using (var writer = XmlWriter.Create(newMessage.BodyWriter.CreateBufferedCopy(int.MaxValue).CreateReader().ReadSubtree(), writerSettings))
        {
            clonedMessage.WriteBodyContents(writer);
        }

        // 复制原消息的头部和属性
        foreach (var header in clonedMessage.Headers)
        {
            newMessage.Headers.Add(header);
        }
        foreach (var prop in clonedMessage.Properties)
        {
            newMessage.Properties[prop.Key] = prop.Value;
        }

        return newMessage;
    }

    public object[] DeserializeReply(Message message, object[] parameters)
    {
        return _originalFormatter.DeserializeReply(message, parameters);
    }
}

再通过端点行为注入自定义格式化器:

public class CustomFormatterBehavior : IEndpointBehavior
{
    public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) { }

    public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
    {
        foreach (var operation in clientRuntime.ClientOperations)
        {
            operation.Formatter = new CustomClientFormatter(operation.Formatter);
        }
    }

    public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher) { }

    public void Validate(ServiceEndpoint endpoint) { }
}

最后在客户端实例中添加该行为:

var client = new MyServiceClient();
client.Endpoint.Behaviors.Add(new CustomFormatterBehavior());

方案2:预转义0x07字符

在构造Request对象时,手动将0x07替换为XML实体,从源头上避免触发字符检查:

// 假设Request类的SerializedData字段包含分隔符
request.SerializedData = request.SerializedData.Replace("\a", "");

Message wcfMessage = Message.CreateMessage(MessageVersion.Soap12WSAddressing10, "MyServiceAction", request);
var wcfMessageXml = wcfMessage.ToString();

注意:需确认服务端能正确解析预转义的实体,避免兼容性问题。

方案3:反射修改内部XmlWriterSettings(临时 workaround)

通过反射修改WCF Message内部使用的XmlWriterSettings,强制关闭字符检查:

var request = new Request(...);
Message wcfMessage = Message.CreateMessage(MessageVersion.Soap12WSAddressing10, "MyServiceAction", request);

// 反射获取并修改内部设置
var bodyWriterProp = typeof(Message).GetProperty("BodyWriter", BindingFlags.Instance | BindingFlags.NonPublic);
var bodyWriter = bodyWriterProp?.GetValue(wcfMessage);
var settingsField = bodyWriter?.GetType().GetField("_xmlWriterSettings", BindingFlags.Instance | BindingFlags.NonPublic);
if (settingsField != null)
{
    var settings = (XmlWriterSettings)settingsField.GetValue(bodyWriter);
    settings.CheckCharacters = false;
}

var wcfMessageXml = wcfMessage.ToString();

注意:此方法依赖.NET WCF的内部实现,后续版本可能失效,仅作为临时应急方案。

总结

优先选择方案1,这是符合WCF扩展规范的方式,兼容性和可维护性最好;若对象结构简单,方案2是最轻便的选择;方案3仅建议在紧急场景下临时使用。

内容的提问来源于stack exchange,提问作者Andy W

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 22:47:39