ASP.NET Core Web API 自定义输出格式化程序详解
本文介绍了 ASP.NET Core Web API 的输出格式化机制。涵盖了内置 JSON 与 XML 格式的添加及配置方法,如何利用 [Produces] 过滤器强制指定内容类型,以及通过扩展 OutputFormatter 类实现 Protocol Buffers 高效序列化的完整步骤。
1. 简单介绍
ASP.NET Core Web API 是构建 RESTful 应用程序的核心工具,支持 HTTP 内容协商,并默认提供了 JSON 和 XML 格式的序列化支持。此外,框架还支持自定义格式化程序、超媒体链接生成及跨资源共享(CORS)等特性。
以下是一个典型的 ValuesController 示例,展示了基于特性的路由和基本 HTTP 操作:
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
// GET api/values
[HttpGet]
public ActionResult<IEnumerable<string>> Get()
{
return new string[] { "value1", "value2" };
}
// GET api/values/5
[HttpGet("{id}")]
public ActionResult<string> Get(int id)
{
return "value";
}
// POST api/values
[HttpPost]
public void Post([FromBody] string value)
{
}
// PUT api/values/5
[HttpPut("{id}")]
public void Put(int id, [FromBody] string value)
{
}
// DELETE api/values/5
[HttpDelete("{id}")]
public void Delete(int id)
{
}
}控制器上标记了 [Route("api/[controller]")]`,调试运行后访问 https://localhost:5000/api/values 即可获取数据。
2. 自定义格式化(Format)
第1步:返回特定格式的操作结果
目的:确保某些接口始终返回固定的数据格式(如纯文本或 JSON),忽略客户端的 Accept 头请求。
入口:控制器类。
动作:使用辅助方法或直接返回特定类型的 IActionResult。
若要从继承自 Controller 的类中返回 JSON,可使用 Json() 方法:
[HttpGet]
public JsonResult Get()
{
return Json(new User());
}此时 Content-Type 将为 application/json。若要返回纯文本,可使用 Content() 方法:
[HttpGet]
public ContentResult Get()
{
return Content("result");
}上述代码将返回 text/plain(注:原文档此处标注为 test/plan,实为笔误)。对于包含复杂逻辑的多条件返回,建议使用 IActionResult 作为返回值类型。
第2步:配置格式化程序
若需支持非默认的序列化格式(如 XML),需在项目依赖中添加相应包,并在 ConfigureServices 中进行配置。输入格式化由模型绑定处理,而输出格式化由 IOutputFormatter 体系负责。
第3步:添加对 XML 格式的支持
准备条件:安装 Microsoft.AspNetCore.Mvc.Formatters.Xml NuGet 包。
操作:在 ConfigureServices 中添加 XML 序列化器。
启用完整的 XML 序列化器:
services.AddMvc()
.AddXmlSerializerFormatters()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1);仅添加输出格式化器(无需反序列化 XML 请求体时):
services.AddMvc(options => {
options.OutputFormatters.Add(new XmlSerializerOutputFormatter());
}).SetCompatibilityVersion(CompatibilityVersion.Version_2_1);也可选择使用 DataContractSerializer 进行序列化:
services.AddMvc(options => {
options.OutputFormatters.Add(new XmlDataContractSerializerOutputFormatter());
});第4步:强制特定格式化
当需要限制某个接口仅返回特定格式(如仅 JSON)时,可使用 [Produces] 过滤器:
[HttpGet("{id}", Name = "Get")]
[Produces("application/json")]
public string Get(int id)
{
return "value";
}默认情况下,返回 string 类型会生成 text/plain。若希望移除该行为,可在服务配置中移除对应的输出格式化器。移除后,若客户端不接受其他格式,将返回 406 Not Acceptable。
同样,移除 HttpNoContentOutputFormatter 后,返回 null 的对象操作将直接返回 204 No Content,而非 JSON 中的 null 或 XML 中的空元素。
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(options => {
options.OutputFormatters.RemoveType<TextOutputFormatter>();
options.OutputFormatters.RemoveType<HttpNoContentOutputFormatter>();
}).SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}第5步:响应格式 URL 映射
客户端可以通过 URL 路径中的文件扩展名(如 .json、.xml)来请求特定格式。需在路由模板中声明格式参数,并应用 [FormatFilter]。
[FormatFilter]
public class UserController : Controller
{
// GET: api/User/GetById/5.json
[HttpGet]
[Route("[controller]/[action]/{id}.{format?}")]
public IActionResult GetById(int id)
{
return Content("xxx");
}
}路由示例:
- /User/GetById/5:使用默认输出格式。
- /User/GetById/5.json:尝试以 JSON 格式输出。
- /User/GetById/5.xml:尝试以 XML 格式输出。
第6步:自定义格式化程序 - Protocol Buffers (protobuf)
Protocol Buffers 是一种高效的结构化数据存储格式。以下演示如何在 ASP.NET Core Web API 中集成 Protobuf 输出格式。
第1步:引入 Protobuf-net 依赖
在项目引用中添加 protobuf-net 库。
第2步:创建 ProtobufFormatter 类
继承 OutputFormatter 并重写 WriteResponseBodyAsync 方法,将对象序列化为二进制流。
public class ProtobufFormatter : OutputFormatter
{
public string ContentType { get; private set; }
public ProtobufFormatter()
{
ContentType = "application/proto";
SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse("application/proto"));
}
public override Task WriteResponseBodyAsync(OutputFormatterWriteContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
var response = context.HttpContext.Response;
Serializer.Serialize(response.Body, context.Object);
return Task.FromResult(0);
}
}第3步:定义数据契约
需要序列化的实体类必须添加 [ProtoContract],字段添加 [ProtoMember] 并指定序号,以保证序列化顺序一致。
[ProtoContract]
public class User
{
[ProtoMember(1)]
public int Id { get; set; }
[ProtoMember(2)]
public string Name { get; set; }
[ProtoMember(3)]
public int Age { get; set; }
}第4步:修改 UserController
在控制器中使用新创建的 Formatter,并配合 [Produces] 指定协议。
[Route("api/[controller]")]
[ApiController]
[FormatFilter]
public class UserController : Controller
{
private IEnumerable<User> users;
public UserController()
{
users = new User[] {
new User(){ Id=1,Name="Bob",Age = 20},
new User(){ Id=2,Name="Tom",Age = 22}
};
}
// GET: api/User
[HttpGet]
[Produces("application/proto")]
public IEnumerable<User> Get()
{
return users;
}
}第5步:注册 Formatter
在 ConfigureServices 中将 ProtobufFormatter 添加到输出格式化器列表中。
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(options => {
options.OutputFormatters.Add(new ProtobufFormatter());
}).SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}第6步:客户端验证
创建一个控制台应用,通过 HTTP 请求获取二进制流并使用 protobuf-net 进行反序列化:
class Program
{
static void Main(string[] args)
{
HttpClient client = new HttpClient();
var stream = client.GetStreamAsync("https://localhost:44358/api/User").Result;
var users = Serializer.Deserialize<List<User>>(stream);
foreach (var user in users)
{
Console.WriteLine($"Id:{user.Id} - Name:{user.Name} - Age:{user.Age}");
}
Console.ReadKey();
}
}运行后,客户端将正确解析服务器发送的二进制 Protobuf 数据并打印用户信息。
以上就是 ASP.NET Core Web API 自定义输出格式化程序的详细内容,更多关于 ASP.NET Core API 高级配置的资料请关注本站其它相关文章!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









