

.NET宝藏API之:OutputFormatter,格式化输出对象 - 畅饮无绪
source link: https://www.cnblogs.com/cool-net/p/16176643.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

.NET宝藏API之:OutputFormatter,格式化输出对象
相信大家在项目中都用过统一响应参数模板。
先声明一个响应模板类:
public class ResponseDto
{
public int code { get; set; }
public string msg { get; set; }
public object data { get; set; }
}
再定义返回成功和失败的方法:
public IActionResult Success(object data)
{
return ......
}
public IActionResult Fail(string msg)
{
return ......
}
在接口返回时统一调用:
[HttpGet]
public IActionResult Get()
{
var data = new WeatherForecast() { Date = DateTime.Now };
return Success(data);
}

当然了,这篇文章所讲的OutputFormatter
和上面的统一模板不冲突哈,存在共通之处,都是格式化响应参数嘛,拿来做个引子。
OutputFormatter
OutputFormatter
是所有格式化输出的基类,有唯一的子类:TextOutputFormatter
,同时TextOutputFormatter
又有一大堆子类:
JsonOutputFormatter
NewtonsoftJsonOutputFormatter
StringOutputFormatter
SystemTextJsonOutputFormatter
XmlDataContractSerializerOutputFormatter
XmlSerializerOutputFormatter
如果不配置任何响应参数输出格式,asp.net core api
响应参数默认的输出格式就是json
。
猴:这个接口给我返回xml
,我不要json
。
我:你是不是脑子有毛病?好好的json
不用用xml
。
得,前端大佬得要求还是得满足不是,这时候有些同学是不是已经去百度:.Net怎么将对象转换成xml?
No
No
No
,这时候就轮到OutputFormatter
的孙子 XmlDataContractSerializerOutputFormatter
出场了。
只需要简单给接口配置一个属性就搞定啦。
[Produces("application/xml")]
[HttpGet]
public WeatherForecast Get()
{
return new WeatherForecast() { Date = DateTime.Now };
}
我们来运行看一看:

wtf
,怎么会406
。
406:表示客户端无法解析服务端返回的内容。说白了就是后台的返回结果前台无法解析就报406错误。
哦,原来是忘了在Startup
中配置我们的孙子XmlDataContractSerializerOutputFormatter
。
services.AddControllers((c) =>
{
c.OutputFormatters.Add(new XmlDataContractSerializerOutputFormatter());
});

注意:不只是没有在Startup
中会出现406
哦,以下情况也会出现:
- contentType不存在
- contentType与响应参数不匹配
OutputFormatter扩展
上面介绍了内置OutputFormatter
的使用,那如果我们想自定义呢?当然也是可以的。
下面我们就用自定义的OutputFormatter
实现顶部响应模板的效果:
public class ObjectOutputFormatter : TextOutputFormatter
{
public ObjectOutputFormatter()
{
SupportedEncodings.Add(Encoding.UTF8);
SupportedEncodings.Add(Encoding.Unicode);
// 这就是我们自定义contentType的名称
SupportedMediaTypes.Add("text/object");
}
public override async Task WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
if (selectedEncoding == null)
{
throw new ArgumentNullException(nameof(selectedEncoding));
}
string text = JsonConvert.SerializeObject(new ResponseDto()
{
msg = "成功,自定义的哦",
code = 200,
data = context.Object
});
var response = context.HttpContext.Response;
await response.WriteAsync(text, selectedEncoding);
}
}
[Produces("text/object")]
[HttpGet]
public WeatherForecast Get()
{
return new WeatherForecast() { Date = DateTime.Now };
}
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers((c) =>
{
c.OutputFormatters.Add(new XmlDataContractSerializerOutputFormatter());
// 我们自定义的输出格式
c.OutputFormatters.Add(new ObjectOutputFormatter());
});
}
搞定,我们来看看效果:

ActionFilterAttribute
有些同学可能会想到过滤器,是的,上面的效果过滤器也能实现:
public class ResultFilter : ActionFilterAttribute
{
public override void OnResultExecuting(ResultExecutingContext context)
{
ResponseDto result = new ResponseDto();
result.code = 200;
result.msg = "成功,ResultFilter";
var properties = context.Result.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public);
result.data = properties.FirstOrDefault(c => c.Name == "Value").GetValue(context.Result);
context.Result = new JsonResult(result);
base.OnResultExecuting(context);
}
}
[TypeFilter(typeof(ResultFilter))]
[HttpGet]
public WeatherForecast Get()
{
return new WeatherForecast() { Date = DateTime.Now };
}

猴:有了过滤器为什么还搞个OutputFormatter
呢?
我:不能因为过滤器可以实现同样的功能就认为OutputFormatter
多余了,很显然过滤器的操作对象是请求/响应上下文,而OutputFormatter
的操作对象则是响应参数。再说了,ActionFilterAttribute
过滤器只是众多过滤器的一种。
猴:那过滤器和自定义OutputFormatter
一起用会是什么效果呢?是不是像下面这样?

我:不是,过滤器和自定义OutputFormatter
同时使用,生效的只有过滤器,不信可以打断点试一下哦。
[Produces("text/object")]
[TypeFilter(typeof(ResultFilter))]
[HttpGet]
public WeatherForecast Get()
{
return new WeatherForecast() { Date = DateTime.Now };
}

具体原因在这里就不细说了,等后面再分享(其实我也还没弄清楚,逼着自己去了解)
好了,这期的宝藏API
就到这了,下期再见哦,如果有下期的话。
Recommend
-
110
Erlang Elixir GTD OmniFocus 时间管理 工具控
-
24
2018年7月14日至8月31日,用户使用中国银行手机银行APP在友宝自助贩售机扫码购水,可享受1折优惠,单笔最高优惠3元,同一客户活动期间每日可享受1次优惠,...
-
67
京东目前有夏日畅饮季酒水促销活动(PC端|APP端),商品低至第二件半价/还有满199-100元活动;整点还有199-100元神券可抢(京享值5000以上,每日0/10/15...
-
34
In this seventh post, I want to write about, how to send your Data in different formats and types to the client. By default the ASP.NET Core Web API sends the data as JSON, but there are some more ways to send the data.
-
9
玩acm的都清楚,cin/cout在大家眼里跟没有一样,凡输入输出都是用c的函数的。 可偏偏c中没有bool这个类型,好吧,其实输出bool是当整形输出的。 #include <cstdio.h> int main() { bool b = true; printf("%...
-
16
dotnet 使用 TypeNameFormatter 库格式化输出反射泛型类型默认的反射输出带泛型的类型,都会使用反引号的字符串。使用 TypeNameFormatter 库可以输出贴近代码的输出 默认的类型的输出是和代码写的方法不相同,如获取 List<int>
-
3
微信小程序,制作属于自己的Icon图标 最近在接手一个微信小程序,发现里面的图标都是...
-
7
Asp.Net在线预览Word文档的解决方案与思路 前几天有个老项目找到我,有多老呢?比我工作年...
-
5
举杯畅饮的姐姐们剧情简介 2023年上映,由罗健玮,王启蘅执导,金莎,刘芸,王以纶,卢勇,姜嫄,韩秋池,宋沐心等主演的《举杯畅饮的姐姐们》...
-
8
无限畅饮的泳池派对,开启百事夏日营销 作者: 中三树 ...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK