ASP.NET Core Web API 自定义输出格式化程序详解

闻溪
闻溪
发布时间:2026-10-16 | 4人浏览过
原创

本文介绍了 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 高级配置的资料请关注本站其它相关文章!

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表