在asp.net core 下定义统一的入参和出参格式

在使用.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,一经查实,立即删除!

相关文章

泰勒定理的奇闻轶事

全世界只有3.14 %的人关注了青少年数学之旅泰勒展式 (Taylor expansion) 的剩余项救人一命&#xff01;在俄国革命期间&#xff08;1917年左右&#xff09;&#xff0c;数学物理学家塔姆 (Igor Tamm) 外出找食物&#xff0c;在靠近敖德萨 (Odessa) 的乡间被反共产主义的保安人员…

6月统计|.NET薪资一旦高起来,岂是其他语言能比的!

全国程序员6月平均薪资出来了&#xff0c;帝都和魔都平均工资超过18k&#xff0c;你被平均了吗&#xff1f;而中位数17k&#xff0c;你拖后腿了吗&#xff1f;当然&#xff0c;.NET开发者的目标不是平均工资&#xff0c;而是double&#xff01;年初跳槽季&#xff0c;腾讯、阿里…

剑桥大学的下午茶,为何能喝出六十位诺贝尔奖获得者?

全世界只有3.14 %的人关注了青少年数学之旅英国人的骄傲是他们有世界上最古老的大学&#xff0c;创立于1209年的剑桥大学。英国剑桥大学每天下午有两个小时的时间&#xff0c;常常有计划、有组织地安排不同学科的权威教授一起在学校咖啡屋或茶园共进下午茶。在这里&#xff0c;…

使用bat来运行cygwin,执行脚本(命令)

2019独角兽企业重金招聘Python工程师标准>>> 这是一个没有意义的问题。 既然要跑脚本。为啥不直接在linux服务器上运行。 这个不是个人能决定的。 一般我都将功能写成jar&#xff0c;或者py, 然后编写bat文件&#xff0c; 如果是java的话&#xff0c;“java -jar…

.NET 下载、文档访问新姿势

dot.net 新的重定向Intro不知道大家之前有没有注意过&#xff0c;如果你访问 https://dot.net 的时候会自动地重定向到 https://dotnet.microsoft.com&#xff0c;想要访问 https://dot.net/download 的时候还是会重定向到 https://dotnet.microsoft.com&#xff0c;不会带着…

excel保存成matlab,matlab数据保存为excel文件

读取&#xff1a;A xlsread(‘Excel路径Excel的名称‘&#xff0c;‘工作表名称‘)例子&#xff1a;A xlsread(‘创新班.xlsx‘,‘Sheet2‘)A xlsread(‘创新班.xlsx‘,‘Sheet2‘,‘a1:c1‘) %读取a1 b1 c1的数据不写工作表名称&#xff0c;默认是第一个。写入&#xff1a;…

客户想你死系列,哈哈哈设计师不容易啊! | 今日最佳

全世界只有3.14 % 的人关注了青少年数学之旅&#xff08;图源网络&#xff0c;侵权删&#xff09;学到了吗&#xff1f;↓ ↓ ↓

DropDownList 選項改變確認腳本

需要這個, 到網找了某先生的腳本改了改 staticpublicstringDropDownListSelectChangeConfirmScript(stringdropDownListId,stringmessage){ string script " <script> \n" " var fooIndex; \n" " function saveIndexes() \n&…

王炸!Azure云助力.NET6现高光时刻(VS2022实战尝鲜)

Azure 是一个云平台&#xff0c;旨在简化构建新式应用程序的过程。无论是选择完全在 Azure 中托管应用程序&#xff0c;还是使用 Azure 服务扩展本地应用程序&#xff0c;Azure 都可以帮助你创建可缩放且可维护的可靠应用程序。凭借你已在使用的工具&#xff08;如 Visual Stud…

求生之路:博士生涯的17条简单生存法则

全世界只有3.14 % 的人关注了青少年数学之旅Next Scientist 是一个专门帮助博士生获取并保持动力、实现毕业和指导在业界求职的网站。本文作者 Julio Peironcely 就是 Next Scientist 的创始人和编辑&#xff0c;曾在荷兰莱顿大学的 PhD 期间做代谢组学和代谢产物鉴定的研究。在…

如何让自己更自律

之前写过一篇如何克服拖延的文章《想得很好&#xff0c;做起来总是不行&#xff1f;》&#xff0c;这次聊得更主动一些&#xff0c;「如何让自己变得自律」&#xff0c;更积极主动地拥抱未来的自己。Sam Thomas Davies曾经精辟地概括过「自律」。他认为自律就是学会抵抗。不管你…

Linux集群服务知识点总结及通过案例介绍如何实现高性能web服务(三)

三&#xff1a;通过corosyncpacemaker实现web服务高可用&#xff0c;主要实现步骤&#xff1a;既然给web应用服务器做高可用&#xff0c;那么httpd进程就不能开机自动运行&#xff0c;而且当前httpd服务属于停止状态&#xff0c;有corosync来自动启动某台的httpd进程12[rootRea…

java hashmap实例,关于java中的HashMap的实例操作

HashMap简介&#xff1a;1、以(键&#xff0c;值)对存储数据。2、不允许有重复的键&#xff0c;但允许有重复的值。3、不同步(多个线程可以同时访问)相关视频教程推荐&#xff1a;java在线学习实例演示如下&#xff1a;1、添加HashMap hash_map new HashMap();hash_map.put( &…

WPF实现仪表盘(刻度跟随)

WPF开发者QQ群&#xff1a; 340500857 | 微信群 -> 进入公众号主页 加入组织“ 前言&#xff0c;接着上一篇圆形进度条。”欢迎转发、分享、点赞、在看&#xff0c;谢谢~。 01—效果预览效果预览&#xff08;更多效果请下载源码体验&#xff09;&#xff1a;02—代码如下一…

数学特级教师:数学除了做习题,我还他让他们看这十部纪录片!

全世界只有3.14 % 的人关注了青少年数学之旅今天我们要向大家强烈推荐一个分享数学知识、严选数学好物公众号“数学好物”。“数学好物”是一个致力为数学爱好者与家长&#xff0c;提供丰富的数学文化、数理思维知识、最新数学好物的公众号。就是他啦&#xff1a;长按二维码可以…

自适应布局

浮动 一列绝对定位,一列用margin撑开空间 margin负值:主体用一层包裹,浮动,内层用margin留出空间;其他列浮动,使用margin调整到空出的位置 1 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"2 "http://www.w3.org/TR/html4/strict.dtd">3 …

Hello Blazor:(2)集成Tailwind CSS

Blazor默认集成了bootstrap&#xff0c;对于我这种后端出身&#xff0c;对CSS一知半解的.NET开发人员来说&#xff0c;使用起来还是有一定难度的。好不容易才学到点皮毛&#xff0c;结果前端人员居然告诉我&#xff0c;bootstrap已经过时了&#xff0c;现在主流都用Tailwind CS…

一文让你掌握单元测试的Mock、Stub和Fake

单元测试中有几个神秘的概念&#xff0c;它们就是Mock&#xff0c;模拟对象&#xff1b;Stub&#xff0c;存根&#xff1b;Fake&#xff0c;伪对象&#xff0c;它们听起来很类似&#xff0c;也很容易混淆&#xff0c;让我们通过这篇文章揭开它们神秘的面纱&#xff0c;探索其幽…

Jafka源码粗略解读之二--关于JMX

2019独角兽企业重金招聘Python工程师标准>>> JMX Jafka里用到了JMX&#xff0c;之前也没用过&#xff0c;迅速突击了一下&#xff0c;感觉还是挺简单的&#xff1a; 有一篇文章用一个例子介绍JMX怎么使用的&#xff0c;简洁明了&#xff1a;http://www.javalobby.or…

参数化的RBAC模型

1 动机 基于角色的访问控制(RBAC)模型被普遍认为是一种有效的访问控制模型&#xff0c;它比传统的自主访问控制(DAC)和强制访问控制(MAC)具有更高的灵活性和更好的扩展性。 在实际应用中&#xff0c;随着企业规模以及信息系统规模逐渐扩大&#xff0c;系统中角色的数目也随之急…