.NET Web API如何配置XML格式化器

发布时间 - 2026-02-02 00:00:00    点击率:
.NET 6+ Web API 默认不支持 XML 响应,因移除了 XmlSerializerOutputFormatter,需手动安装 Microsoft.AspNetCore.Mvc.Formatters.Xml 包并注册该格式化器,且模型须满足无参构造、public 属性等要求。

为什么默认不支持 XML 响应

.NET 6+ 的 Web API 模板默认只注册 SystemTextJsonOutputFormatter,完全移除了对 XML 的自动支持。即使你返回 IActionResult 或启用了 [Produces("application/xml")],请求带 Accept: application/xml 也会直接 406 Not Acceptable。

添加 XmlSerializerOutputFormatter 的正确方式

必须显式注册基于 XmlSerializer 的格式化器(XmlDataContractSerializer 已被弃用且不推荐用于 Web API)。注意:.NET 5+ 不再内置 XML 支持包,需先安装 NuGet 包:

dotnet add package Microsoft.AspNetCore.Mvc.Formatters.Xml

然后在 Program.cs 中注册:

builder.Services.AddControllers(options =>
{
    options.OutputFormatters.Add(new XmlSerializerOutputFormatter());
    // 可选:禁用默认的 JSON 格式化器(仅需 XML 时)
    // options.OutputFormatters.RemoveType();
});

关键点:

  • XmlSerializerOutputFormatter 要求模型类有无参构造函数,且属性必须是 public get/set
  • 不支持 record 类型(会抛 InvalidOperationException: Type 'X' cannot be serialized
  • 若控制器方法返回 Task,确保实际返回值类型可被 XmlSerializer 序列化(如 Ok(MyModel)

处理 XML 请求(POST/PUT)

仅配置输出格式化器不够——接收 XML 请求体还需注册输入格式化器:

builder.Services.AddControllers(options =>
{
    options.InputFormatters.Add(new XmlSerializerInputFormatter(options));
    options.OutputFormatters.Add(new XmlSerializerOutputFormatter());
});

此时需确保请求头包含 Content-Type: application/xml,且 XML 结构与模型字段名严格匹配(区分大小写,无命名空间更稳妥)。常见失败原因:

  • XML 根节点名 ≠ 模型类名(XmlRoot 特性可覆盖)
  • 字段名含下划线或驼峰,但 XML 使用短横线(如 )→ 需加 [XmlElement("user-name")]
  • 传了空字符串给非 nullable 引用类型字段 → 反序列化失败

调试 406 或空响应的快速检查项

当 XML 响应不生效时,优先验证以下三点:

  • 是否漏装 Microsoft.AspNetCore.Mvc.Formatters.Xml 包?没有它,XmlSerializerOutputFormatter 类型根本不存在
  • 是否在 AddControllers() 后才调用 Build()?顺序错误会导致注册失效
  • 是否误用了 serv

    ices.AddMvc()
    (已过时)?.NET 6+ 推荐统一用 AddControllers() + AddEndpointsApiExplorer()
  • 是否在 Startup.Configure() 中忘了调用 app.UseRouting()app.UseEndpoints()?中间件链中断会导致格式化器不触发

XML 格式化器本身不处理缩进或编码声明,生成的 XML 默认无换行、UTF-8 无 BOM。如果需要美化输出,得自己封装 XmlWriterSettings 并继承 XmlSerializerOutputFormatter —— 这部分容易被低估工作量。


# js  # json  # 编码  # app  # microsoft  # .net  # 为什么  # mvc  # 中间件  # 命名空间  # 封装  # 构造函数  # xml  # 字符串  # 继承  # 值类型  # 引用类型  # public  # Nullable  # bom  # 不支持  # 移除  # 字段名  # 序列化  # 也会  # 已被  # 下划线  # 这部  # 不存在  # 可选 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: 微信小程序 input输入框控件详解及实例(多种示例)  合肥制作网站的公司有哪些,合肥聚美网络科技有限公司介绍?  Win11摄像头无法使用怎么办_Win11相机隐私权限开启教程【详解】  JS弹性运动实现方法分析  Laravel集合Collection怎么用_Laravel集合常用函数详解  mc皮肤壁纸制作器,苹果平板怎么设置自己想要的壁纸我的世界?  百度输入法ai组件怎么删除 百度输入法ai组件移除工具  制作公司内部网站有哪些,内网如何建网站?  电商网站制作多少钱一个,电子商务公司的网站制作费用计入什么科目?  阿里云网站搭建费用解析:服务器价格与建站成本优化指南  Laravel如何集成Inertia.js与Vue/React?(安装配置)  HTML5段落标签p和br怎么选_文本排版常用标签对比【解答】  Laravel中间件如何使用_Laravel自定义中间件实现权限控制  WordPress 子目录安装中正确处理脚本路径的完整指南  Laravel怎么清理缓存_Laravel optimize clear命令详解  如何确认建站备案号应放置的具体位置?  极客网站有哪些,DoNews、36氪、爱范儿、虎嗅、雷锋网、极客公园这些互联网媒体网站有什么差异?  Laravel中的Facade(门面)到底是什么原理  Laravel如何监控和管理失败的队列任务_Laravel失败任务处理与监控  Laravel怎么发送邮件_Laravel Mail类SMTP配置教程  百度浏览器如何管理插件 百度浏览器插件管理方法  Laravel Pest测试框架怎么用_从PHPUnit转向Pest的Laravel测试教程  Laravel请求验证怎么写_Laravel Validator自定义表单验证规则教程  Laravel如何使用Eloquent进行子查询  Claude怎样写约束型提示词_Claude约束提示词写法【教程】  php打包exe后无法访问网络共享_共享权限设置方法【教程】  Win11怎么设置虚拟桌面 Win11新建多桌面切换操作【技巧】  html如何与html链接_实现多个HTML页面互相链接【互相】  如何快速使用云服务器搭建个人网站?  Laravel Docker环境搭建教程_Laravel Sail使用指南  如何用搬瓦工VPS快速搭建个人网站?  Laravel Eloquent模型如何创建_Laravel ORM基础之Model创建与使用教程  Laravel如何使用Laravel Vite编译前端_Laravel10以上版本前端静态资源管理【教程】  javascript如何操作浏览器历史记录_怎样实现无刷新导航  图册素材网站设计制作软件,图册的导出方式有几种?  如何自己制作一个网站链接,如何制作一个企业网站,建设网站的基本步骤有哪些?  laravel怎么通过契约(Contracts)编程_laravel契约(Contracts)编程方法  Laravel怎么实现观察者模式Observer_Laravel模型事件监听与解耦开发【指南】  Python3.6正式版新特性预览  香港服务器建站指南:外贸独立站搭建与跨境电商配置流程  PHP怎么接收前端传的文件路径_处理文件路径参数接收方法【汇总】  如何快速生成专业多端适配建站电话?  rsync同步时出现rsync: failed to set times on “xxxx”: Operation not permitted  企业网站制作这些问题要关注  HTML5打空格有哪些误区_新手常犯的空格使用错误【技巧】  浅谈javascript alert和confirm的美化  如何打造高效商业网站?建站目的决定转化率  详解vue.js组件化开发实践  Laravel怎么实现一对多关联查询_Laravel Eloquent模型关系定义与预加载【实战】  Javascript中的事件循环是如何工作的_如何利用Javascript事件循环优化异步代码?