客户要求ASP.NET Core API返回特定格式,怎么办?(续2)

前言

前2次,我们都是假设客户需要返回不同的字符串格式。

但是,有可能客户要求的返回是非本文格式,比如文件流。

怎么办?

思路

前提,当然还是使用同一API接口,不影响现有使用方式。

虽然ASP.NET Core Web API默认使用SystemTextJsonOutputFormatter格式化响应,但是OutputFormatters集合里其实包含了StreamOutputFormatter

13f262f3c298d493c2dc27e2e3f65c3d.png

那么实现目标就转化为,怎么让Web API使用StreamOutputFormatter

DefaultOutputFormatterSelector

通过查看dotnet/aspnetcore源代码,我们找到了DefaultOutputFormatterSelector,它是选择IOutputFormatter以写入对当前请求的响应的默认实现:

219a21a26a76e84acf36d190bbe9f870.png

其中,选择IOutputFormatter具体实现是通过判断CanWriteResult方法,代码如下:

foreach (var formatter in formatters)
{
    formatterContext.ContentType = new StringSegment();
    formatterContext.ContentTypeIsServerDefined = false;

    if (formatter.CanWriteResult(formatterContext))
    {
        return formatter;
    }
}

StreamOutputFormatter是这样实现CanWriteResult方法的:

public bool CanWriteResult(OutputFormatterCanWriteContext context)
{
    if (context == null)
    {
        throw new ArgumentNullException(nameof(context));
    }

    // Ignore the passed in content type, if the object is a Stream.
    if (context.Object is Stream)
    {
        return true;
    }

    return false;
}

那么实现目标就转化为,怎么让Web API返回的是Stream

操作返回类型

微软官方文档ASP.NET Core Web API 中控制器操作的返回类型[1]提到,返回类型除了支持特定类型之外,还支持ActionResult<T>

ActionResult<T>可以返回从ActionResult派生的类型或返回特定类型:

c3b8014ea70c629bcbc209eec39259a7.png

那么实现目标就转化为,将返回类型设为ActionResult<T>,根据条件返回T,或者返回特定ActionResult派生类,例如FileResult

实现

具体实现代码如下,如果Accept Headertext/json则返回文件流:

[HttpGet]
public ActionResult<IEnumerable<WeatherForecast>> Get()
{
    var rng = new Random();
    var result = Enumerable.Range(1, 5).Select(index => new WeatherForecast
    {
        Date = DateTime.Now.AddDays(index),
        TemperatureC = rng.Next(-20, 55),
        Summary = Summaries[rng.Next(Summaries.Length)]
    })
    .ToArray();

    HttpContext.Request.Headers.TryGetValue("Accept", out var acceptValue);
    if (acceptValue.ToString() == "text/json")
    {
        using (var memory = new MemoryStream())
        {
            using (var writer = new StreamWriter(memory))
            {
                writer.Write(System.Text.Json.JsonSerializer.Serialize(result));
                writer.Flush();
            }

            return File(memory.ToArray(), "text/json", "WeatherForecast.json");
        } 
    }

    return result;
}

结论

现在,只需要客户在每个API请求加上Accept Header即可满足需求。

如果你觉得这篇文章对你有所启发,请关注我的个人公众号”My IO“

参考资料

[1]

ASP.NET Core Web API 中控制器操作的返回类型: https://docs.microsoft.com/zh-cn/aspnet/core/web-api/action-return-types?view=aspnetcore-5.0

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值