ASP.NET Core 2.2 内容协商与自定义IActionResult和格式化类

前端开发者说 2019-06-20 ⋅ 17 阅读

简介

在 ASP.NET Core 2.2 中,内容协商是一个重要的概念,它允许服务器端根据客户端的请求头部信息选择最适合的响应格式返回给客户端。同时,我们还可以通过自定义 IActionResult 和格式化类来实现更精细的控制和扩展性。

内容协商

内容协商是指在客户端和服务器端之间进行协商,确定响应数据的格式,主要包括以下几种格式:

  • JSON:最常用的数据格式,适合移动设备和前端应用处理
  • XML:适合老式的 SOAP 服务和某些遗留系统
  • 文本:适合输出纯文本内容
  • HTML:适合浏览器直接渲染的内容

ASP.NET Core 使用了 MediaTypeHeaderValue 类来实现内容协商。

按请求头部信息协商内容格式

[Route("api/[controller]")]
[ApiController]
public class SampleController : ControllerBase
{
    [HttpGet]
    [Produces("application/xml", "application/json")] // 指定支持的媒体类型
    public IActionResult GetData()
    {
        var data = new { Name = "John", Age = 42 };

        return Ok(data); // 自动内容协商并返回最佳格式
    }
}

按 URL 后缀协商内容格式

在 Startup.cs 文件的 Configure 方法中,注册内容协商中间件:

app.UseMvc(routes =>
{
    routes.MapRoute(
        name: "default",
        template: "{controller}/{action}/{id?}.{format?}",
        defaults: new { controller = "Home", action = "Index" }
    );
});

上面的代码允许在路由配置中添加可选的 “.format” 后缀来实现内容协商。例如,请求 “/api/sample.xml” 将返回 XML 格式的数据。

自定义 IActionResult 和格式化类

自定义 IActionResult

我们可以继承 IActionResult 接口,并实现自定义的执行逻辑。下面是一个自定义的 IActionResult 示例:

public class CustomJsonResult : IActionResult
{
    private readonly object _data;

    public CustomJsonResult(object data)
    {
        _data = data;
    }

    public async Task ExecuteResultAsync(ActionContext context)
    {
        var json = JsonConvert.SerializeObject(_data);
        var response = context.HttpContext.Response;

        response.ContentType = "application/json";
        await response.WriteAsync(json);
    }
}

我们可以在控制器中返回自定义的 IActionResult,如:

[HttpGet]
public IActionResult GetData()
{
    var data = new { Name = "John", Age = 42 };

    return new CustomJsonResult(data);
}

自定义格式化类

我们还可以自定义格式化类来实现更灵活的内容协商。下面是一个自定义的格式化类示例:

public class CsvOutputFormatter : OutputFormatter
{
    public CsvOutputFormatter()
    {
        SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse("text/csv"));
    }

    protected override bool CanWriteType(Type type)
    {
        // 判断是否支持转换为 CSV 格式
        return typeof(IEnumerable).IsAssignableFrom(type);
    }

    public async override Task WriteResponseBodyAsync(OutputFormatterWriteContext context)
    {
        var response = context.HttpContext.Response;

        var buffer = new StringBuilder();
        var type = context.Object.GetType();
        var properties = type.GetProperties();
        var csvHeader = string.Join(",", properties.Select(p => p.Name));
        buffer.Append(csvHeader);

        var objList = (IEnumerable)context.Object;
        foreach (var obj in objList)
        {
            buffer.AppendLine();

            var csvLine = string.Join(",", properties.Select(p => p.GetValue(obj, null)));
            buffer.Append(csvLine);
        }

        await response.WriteAsync(buffer.ToString());
    }
}

要注册自定义的格式化类,可以在 Startup.cs 文件的 ConfigureServices 方法中添加以下代码:

services.AddMvc(options =>
{
    options.OutputFormatters.Insert(0, new CsvOutputFormatter());
});

然后在控制器中使用自定义的格式化类:

[HttpGet]
[Produces("text/csv")]
public IEnumerable<Person> GetPeople()
{
    // 返回 CSV 格式的数据
    return _repository.GetPeople();
}

结语

ASP.NET Core 2.2 提供了强大的内容协商功能,能够根据客户端的请求头部信息选择最适合的响应格式。通过自定义 IActionResult 和格式化类,我们可以实现更精细的控制和扩展性。希望本文能对你了解 ASP.NET Core 内容协商和自定义 IActionResult 和格式化类有所帮助。


全部评论: 0

    我有话说: