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

.NET Core 3.1 Web API含DOCTYPE的XML POST请求反序列化报错求助

解决.NET Core 3.1 API处理含DOCTYPE的XML请求反序列化失败问题

你的问题根源在于:当XML请求包含DOCTYPE声明时,默认的XML序列化器(无论是XmlSerializer还是DataContractSerializer)会尝试解析外部DTD文件,但.NET Core出于安全考虑,默认禁止了外部实体的解析,导致反序列化过程抛出异常,返回400验证错误。

为什么会失败?

.NET Core中XmlReader的默认DtdProcessing配置是Prohibit,这意味着一旦检测到DOCTYPE声明就会直接抛出异常。你的请求里的DOCTYPE指向了一个外部DTD地址,序列化器尝试加载它时被安全策略阻止,最终触发了"An error occurred while deserializing input data."的错误。

解决方案:自定义XML格式化器,修改DTD处理策略

我们需要自定义XML输入格式化器,调整XmlReaderSettings中的DtdProcessing选项,同时禁用外部实体解析以保证安全。下面分两种序列化器的情况给出解决方案:


情况1:使用XmlSerializer(对应你代码中的AddXmlSerializerFormatters())

  1. 创建自定义的XmlSerializerInputFormatter,重写CreateXmlReader方法:
using Microsoft.AspNetCore.Mvc.Formatters;
using System.Xml;

public class CustomXmlSerializerInputFormatter : XmlSerializerInputFormatter
{
    public CustomXmlSerializerInputFormatter(MvcOptions options) : base(options)
    {
    }

    protected override XmlReader CreateXmlReader(Stream readStream, Encoding encoding)
    {
        var readerSettings = new XmlReaderSettings
        {
            // 忽略DOCTYPE声明,继续反序列化XML内容
            DtdProcessing = DtdProcessing.Ignore,
            // 禁用外部实体解析,防止XXE攻击
            XmlResolver = null
        };
        return XmlReader.Create(readStream, readerSettings);
    }
}
  1. 在Startup.cs中替换默认的XmlSerializerInputFormatter:
public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc(options => 
    { 
        options.RespectBrowserAcceptHeader = true;
        
        // 移除默认的XmlSerializer输入格式化器
        var defaultXmlInputFormatter = options.InputFormatters.OfType<XmlSerializerInputFormatter>().FirstOrDefault();
        if (defaultXmlInputFormatter != null)
        {
            options.InputFormatters.Remove(defaultXmlInputFormatter);
        }
        
        // 添加自定义的XmlSerializer输入格式化器
        options.InputFormatters.Add(new CustomXmlSerializerInputFormatter(options));
    })
    .AddXmlDataContractSerializerFormatters(); // 如果不需要DataContractSerializer可以移除这行
}

情况2:使用DataContractSerializer(对应你代码中的AddXmlDataContractSerializerFormatters())

如果你的API实际使用的是DataContractSerializer,可以创建对应的自定义格式化器:

  1. 自定义XmlDataContractSerializerInputFormatter:
using Microsoft.AspNetCore.Mvc.Formatters;
using System.Xml;
using System.Xml.Serialization;

public class CustomXmlDataContractSerializerInputFormatter : XmlDataContractSerializerInputFormatter
{
    public CustomXmlDataContractSerializerInputFormatter(MvcOptions options) : base(options)
    {
    }

    protected override XmlDictionaryReader CreateXmlReader(Stream readStream, Encoding encoding)
    {
        var readerSettings = new XmlReaderSettings
        {
            DtdProcessing = DtdProcessing.Ignore,
            XmlResolver = null
        };
        var xmlReader = XmlReader.Create(readStream, readerSettings);
        return XmlDictionaryReader.CreateDictionaryReader(xmlReader);
    }
}
  1. 在Startup.cs中替换默认的XmlDataContractSerializerInputFormatter:
public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc(options => 
    { 
        options.RespectBrowserAcceptHeader = true;
        
        // 移除默认的DataContractSerializer输入格式化器
        var defaultDcInputFormatter = options.InputFormatters.OfType<XmlDataContractSerializerInputFormatter>().FirstOrDefault();
        if (defaultDcInputFormatter != null)
        {
            options.InputFormatters.Remove(defaultDcInputFormatter);
        }
        
        // 添加自定义的DataContractSerializer输入格式化器
        options.InputFormatters.Add(new CustomXmlDataContractSerializerInputFormatter(options));
    })
    .AddXmlSerializerFormatters(); // 如果不需要XmlSerializer可以移除这行
}

额外说明

  • 如果你的业务确实需要解析DTD(而不是忽略它),可以将DtdProcessing设置为DtdProcessing.Parse,但务必保持XmlResolver = null,避免加载外部实体导致安全风险(比如XXE注入攻击)。
  • 你的Name实体类和Transform控制器方法不需要做任何修改,只需要调整Startup.cs中的格式化器配置即可。

内容的提问来源于stack exchange,提问作者Naveed Ahmed

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 16:17:54