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

如何确保Refit调用API时始终携带!DOCTYPE声明?

问题

使用Refit调用API时,必须在XML请求内容中包含<!DOCTYPE>声明,否则会收到400错误:

No message type defined for xml root node 'greeting, line 45:16
Technical ID 14f2a71af84#2fef8552034a12

当前配置代码如下:

Program.cs中的Refit客户端配置:

services
    .AddRefitClient<IEndpointApi>(new()
    {
        ContentSerializer = new XmlContentSerializer()
    });

模型类定义:

[XmlSchemaProvider("hello.dtd")]
[XmlType("greeting")]
[XmlRoot("greeting")]
public class Greeting 
{
    [XmlText]
    public string Text { get; set; }
}

Refit客户端接口:

public interface IEndpointApi
{
    [Post("/endpoint")]
    Task<Response> SendData([Body] Greeting greeting);
}

需要实现每次发送请求时,XML内容包含如下格式的DOCTYPE声明:

<?xml version="1.0"?>
<!DOCTYPE greeting SYSTEM "hello.dtd">
<greeting>Hello, world!</greeting> 
解决方案

要在Refit的XML请求中添加DOCTYPE声明,需要自定义XmlContentSerializer,重写序列化逻辑以注入DOCTYPE。

步骤1:创建自定义XmlContentSerializer类

public class CustomXmlContentSerializer : XmlContentSerializer
{
    private readonly string _rootElementName;
    private readonly string _dtdPath;

    public CustomXmlContentSerializer(string rootElementName, string dtdPath)
    {
        _rootElementName = rootElementName;
        _dtdPath = dtdPath;
    }

    protected override XmlWriterSettings CreateXmlWriterSettings()
    {
        var settings = base.CreateXmlWriterSettings();
        // 确保输出XML版本声明
        settings.OmitXmlDeclaration = false;
        return settings;
    }

    public override async Task<HttpContent> SerializeAsync<T>(T item, CancellationToken cancellationToken)
    {
        if (item == null)
            return await base.SerializeAsync(item, cancellationToken);

        var stringWriter = new StringWriter();
        using var xmlWriter = XmlWriter.Create(stringWriter, CreateXmlWriterSettings());
        
        // 写入DOCTYPE声明
        xmlWriter.WriteDocType(_rootElementName, null, _dtdPath, null);
        
        // 序列化对象到XML
        var serializer = new XmlSerializer(typeof(T));
        serializer.Serialize(xmlWriter, item);

        var content = new StringContent(stringWriter.ToString(), Encoding.UTF8, "application/xml");
        return content;
    }
}

步骤2:替换原有序列化器配置

在Program.cs中,用自定义序列化器替换默认的XmlContentSerializer:

services
    .AddRefitClient<IEndpointApi>(new()
    {
        // 传入对应根元素名和DTD路径
        ContentSerializer = new CustomXmlContentSerializer("greeting", "hello.dtd")
    });

步骤3:验证模型特性(可选)

你的Greeting类已标注[XmlRoot("greeting")]和[XmlSchemaProvider("hello.dtd")],这些特性可保留,与自定义序列化器逻辑兼容,确保XML结构符合要求。

修改完成后,每次发送请求时XML内容会自动包含指定的DOCTYPE声明,满足接口校验要求。

内容的提问来源于stack exchange,提问作者H. Pauwelyn

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 02:13:28