在使用.net core 开发Api的过程中,为了统一输入参数的格式,并增加一些全局必须含有的字段,比如:Code,Message,Lang等等,能采取的变通方式还是有几种的,然而都不够优雅,为了需求更优雅的解决方式,本文采用asp.net core支持的自定义模型绑定以及结果过滤方式解决,测试效果达到了预期目的。
MVC过滤器
对于熟悉asp.net 的朋友来说,使用过滤器还是比较容易的,过滤器本身有着严格的顺序,选用哪一种过滤器,必然是经过思考才能进行抉择的,对于输入参数来说,我们想修改参数值,可能比较方便的是选择在操作过滤器上实现。
授权过滤器(Authorization)最先运行,用于确定是否已针对当前请求为当前用户授权。 如果请求未获授权,它们可以让管道短路。
资源过滤器(Resource)是授权后最先处理请求的筛选器。 它们可以在筛选器管道的其余阶段运行之前以及管道的其余阶段完成之后运行代码。 出于性能方面的考虑,可以使用它们来实现缓存或以其他方式让筛选器管道短路。 它们在模型绑定之前运行,所以可以影响模型绑定。
操作过滤器可(Action)以在调用单个操作方法之前和之后立即运行代码。 它们可用于处理传入某个操作的参数以及从该操作返回的结果。不可在 Razor Pages 中使用操作筛选器。
异常过滤器(Exception)用于在向响应正文写入任何内容之前,对未经处理的异常应用全局策略。
结果过滤器(Result)可以在执行单个操作结果之前和之后立即运行代码。 仅当操作方法成功执行时,它们才会运行。 对于必须围绕视图或格式化程序的执行的逻辑,它们很有用。
过滤器在 MVC 操作调用管道中执行,其大致位置如下:
不同类型的过滤器操作顺序如下:
实现结果过滤器的目的
写过滤器的目的是把mvc控制器的Action返回结果加上固定返回格式,比如下图返回一个字符串数组,我们需要的格式是一个包含该内容的json格式。
用户最终接收到的是下列内容。
{
"Code":123,
"Message":"这是一个异常信息",
"Data": ["values1","values2"],
"RequestId":"0001"
}
当然为了实现该目的,你可以定义一个模板类,每个返回值都增加上诸如:Result<IEnumerable<string>>,或者定义一个基类,大家都集成自这个基类,也都可以实现,就是感觉不够优雅。
结果过滤器
可以参考如下实现。
难点:输入参数
输入参数的目的是从下列json中解析出Data结果数据绑定到mvc的action模型上。
{"Data":{
"desc": "string",
"parameters": "string",
"ttid": "string",
"guid": "string"
},"Lang":"zh_cn","RequestId":"ee27c35e-f8f9-4619-aabf-3125e84bcf90"}
如上所示,你可以定义一个模板类或子类,然后同结果一样,但不够优雅优雅~~~~,啊哈哈,强迫症...
这里采用微软提供的模型绑定器解决该问题。ASP.NET Core MVC 中的模型绑定将 HTTP 请求中的数据映射到操作方法参数。 这些参数可能是简单类型的参数,如字符串、整数或浮点数,也可能是复杂类型的参数。 这是 MVC 的一项强大功能,因为不管数据的大小和复杂性,将传入数据映射到对应位置都是经常重复的方案。MVC 通过将绑定抽象出来解决了这一问题,使开发者不必在每个应用中重写同一代码的稍微不同版本。 向类型转换器代码写入自己的文本不仅繁琐乏味,而且容易出错。
先实现一个继承自IModelBinder的类来实现绑定处理的核心工作。
public async Task BindModelAsync(ModelBindingContext bindingContext)
{
if (bindingContext == null)
{
throw new ArgumentNullException(nameof(bindingContext));
}
string modelBindingKey;
if (bindingContext.IsTopLevelObject)
{
modelBindingKey = bindingContext.BinderModelName ?? string.Empty;
}
else
{
modelBindingKey = bindingContext.ModelName;
}
var httpContext = bindingContext.HttpContext;
try
{
var args = await GetRequestValueAsync(httpContext.Request);
httpContext.Items.Add("_Args", args);
var type = bindingContext.ModelType;
var argsType = typeof(Args<>).MakeGenericType(type);
dynamic modelRtn = JsonConvert.DeserializeObject(args, argsType);
if (modelRtn == null)
{
var message = $"序列化输入参数为Args<{type.FullName}>时,结果为不期望的空值";
bindingContext.ModelState.AddModelError(modelBindingKey, message);
return;
}
bindingContext.Result = ModelBindingResult.Success(modelRtn.v);
modelRtn.v = null;
var model = modelRtn.ToNormalizing();
if (string.IsNullOrEmpty(model.rid))
{
model.rid = Guid.NewGuid().ToString("N");
}
httpContext.Items.Add("_ArgsObject", model);
}
catch (Exception exception)
{
bindingContext.ModelState.AddModelError(modelBindingKey, exception, bindingContext.ModelMetadata);
}
}
是时候建立一个ModelBinderProvider来建立上述绑定了。只需要实现IModelBinderProvider接口即可。
public IModelBinder GetBinder(ModelBinderProviderContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
if (context.BindingInfo.BindingSource != null &&
context.BindingInfo.BindingSource.CanAcceptDataFrom(BindingSource.Body))
{
return new QtBodyModelBinder(_options);
}
return null;
}
增加过滤和绑定
services.AddMvc(options => {
options.ModelBinderProviders.Insert(index, new QtBodyModelBinderProvider(options));
options.Filters.Add(typeof(QtResultFilter));
}) ;
应用
控制器内的使用还是按照原有方式,简单明了,而传入的参数和输出的参数已经按照我们的json格式整理了,啊哈哈,终于不用纠结不优雅了~~~~
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/301047.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!相关文章
6月统计|.NET薪资一旦高起来,岂是其他语言能比的!
剑桥大学的下午茶,为何能喝出六十位诺贝尔奖获得者?
使用bat来运行cygwin,执行脚本(命令)
.NET 下载、文档访问新姿势
excel保存成matlab,matlab数据保存为excel文件
客户想你死系列,哈哈哈设计师不容易啊! | 今日最佳
DropDownList 選項改變確認腳本
王炸!Azure云助力.NET6现高光时刻(VS2022实战尝鲜)
求生之路:博士生涯的17条简单生存法则
Linux集群服务知识点总结及通过案例介绍如何实现高性能web服务(三)
java hashmap实例,关于java中的HashMap的实例操作
WPF实现仪表盘(刻度跟随)
数学特级教师:数学除了做习题,我还他让他们看这十部纪录片!
Hello Blazor:(2)集成Tailwind CSS
一文让你掌握单元测试的Mock、Stub和Fake
Jafka源码粗略解读之二--关于JMX
参数化的RBAC模型
- 如何快速搭建一个spring boot项目
- 数据仓库之 Atlas 血缘分析:揭示数据流奥秘
- Minio中出现Non-XML response from server异常
- 【vue2.7.16系列】手把手教你搭建后台系统__登录接口返回信息调整(16)
- Java项目实战II基于Spring Boot的便利店信息管理系统(开发文档+数据库+源码)
- conda安装和使用
- eclipse定制化配置调优、初始化配置指南、可以解决启动慢等问题
- JS中创建函数的几种方式
- leetcode53 Maximum Subarray 最大连续子数组
- symbian系统开发教程(一)
- vue.js的项目实战
- 是什么样的骚操作让应用上线节省90%的时间