在使用.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.taodudu.cc/news/show-908805.html

相关文章:

  • 6月统计|.NET薪资一旦高起来,岂是其他语言能比的!
  • .NET 下载、文档访问新姿势
  • 王炸!Azure云助力.NET6现高光时刻(VS2022实战尝鲜)
  • 如何让自己更自律
  • WPF实现仪表盘(刻度跟随)
  • Hello Blazor:(2)集成Tailwind CSS
  • 使用 ML.NET 进行保险价格预测
  • 面向.NET开发人员的Dapr- actors 构建块
  • 在 .NET 应用中使用 ANTLR
  • 单体系统如何拆分为微服务
  • ABP Framework V4.4 RC 新增功能介绍
  • 我用段子讲.NET之依赖注入(一)
  • 张善友: .NET社区运营 | 2021 中国开发者生态峰会
  • 从零实操基于WSL2 Docker部署Asp.Net Core项目
  • 全部换新-微软复兴.NET,C#10 .NET6 VS2022各个强势!
  • 刘敏:优麒麟开源操作系统运营实践 | DEV. Together 2021 中国开发者生态峰会
  • C# 无意间写了一段线程死锁的代码
  • NLog源码解读——StringBuilderPool
  • ABP Framework:移除 EF Core Migrations 项目,统一数据上下文
  • 关于c#:Filter Serilog日志取决于上下文源到不同的接收器?
  • 打造史上最小尺寸.Net Core单文件应用程序
  • 【汇总】多种方法教你绕过 TPM 2.0 安装 Windows 11 操作系统
  • NET问答: 如何在 dynamic 集合上使用 Linq ?
  • C# 代码生成二维码方法及代码示例(QRCoder)
  • 并行中的分区Partitioner
  • Ant Design Blazor 组件库的路由复用多标签页介绍
  • 基于Yarp实现内网http穿透
  • 不止 Windows 10!Windows 7/8 也能免费升级到 Windows 11
  • 解答网友提问:如何构建动态表达式实现高级查询服务
  • .net core 下的分布式事务锁

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

  1. ASP.NET Core下FreeSql的仓储事务

    ASP.NET Core下FreeSql的仓储事务 山柏小说网 https://www.5186.info 第一步:配置 Startup.cs 注入 引入包 dotnet add package Fr ...

  2. Asp.Net Core下的开源任务调度平台ScheduleMaster—快速上手

    概述 ScheduleMaster是一个开源的分布式任务调度系统,它基于Asp.Net Core平台构建,支持跨平台多节点部署运行. 它的项目主页在这里: https://github.com/hey ...

  3. Asp.Net Core下的开源任务调度平台ScheduleMaster

    从何说起 2017年初的时候,由于当时项目需要做了一个乞丐版定时调度系统,那时候只在单机上实现了核心的调度功能.做这个玩意之前也调研了社区中开源的解决方案,找了几个实地部署试跑了一下,其实都很不错.但 ...

  4. 在ASP.NET Core下使用SignalR技术

    一.前言 上次我们讲到过如何在ASP.NET Core中使用WebSocket,没有阅读过的朋友请参考 WebSocket in ASP.NET Core 文章 .这次的主角是SignalR它为我们提 ...

  5. 【愚公系列】2022年06月 ASP.NET Core下CellReport报表工具基本介绍和使用

    文章目录 前言 一.CellReport报表工具 1.CellReport的特点 2.CellReport的使用前提 3.CellReport的使用 4.运行和配置 前言 在没有计算机以前,人们利用纸 ...

  6. 【笔记】Spring MVC拦截入参、出参实现入参解密,出参加密统一管理

    需求:为提高接口的安全性,对数据传输加密. 前提:Controller层使用@RequestBody接收入参,@ResponseBody出参 入参解密 package com.sep6th.base. ...

  7. ASP.NET Core 下的依赖注入(一)

    本文介绍利用 Microsoft.Extensions.Configuration.Binder.dll 来实现超级简单的注入. 1. appsettings.json 中定义配置 假设我们有如下配置 ...

  8. ASP.NET CORE下用盛派微信SDK取微信openid

    用CORE做项目用到微信的相关东西,听说那个盛派微信SDK很火,自己弄了下,只是简单的用用,用户访问页面取微信openid

  9. mysql多租户schema复制,Asp.net core下利用EF core实现从数据实现多租户(3): 按Schema分离 附加:EF Migration 操作...

    前言 前段时间写了EF core实现多租户的文章,实现了根据数据库,数据表进行多租户数据隔离. 今天开始写按照Schema分离的文章. 其实还有一种,是通过在数据表内添加一个字段做多租户的,但是这种模 ...

最新文章

  1. python3 列表_Python3 列表生成
  2. mysql keepalived双主双活_Keepalived单网络双活双主配置模式
  3. oracle数据库批量操作系统,Oracle批量操作数据库
  4. 如何使用纯 CSS 创建翻牌动画
  5. 【软件-软件设计师】操作系统知识架构图
  6. Java 基础 - 各项集合实现
  7. BDOC generated after customer product id is changed in CRM - CUST_MAT_INF
  8. [转]C#网络编程(同步传输字符串) - Part.2
  9. stl:string:将str中的oldstr替换为newstr
  10. linux下安装配置svn独立服务器
  11. 随机模拟的基本思想和常用采样方法(sampling)
  12. 初中数学知识点总结_初中数学函数知识点总结
  13. Reed-Solomon Codes——RS纠错码
  14. Pytorch实战宝可梦分类-自定义数据集完成宝可梦分类案例分步解析
  15. Web服务器Nginx
  16. 《中国近代史纲要》思维导图复习版
  17. sh: warning: setlocale: LC_ALL: cannot change locale (zh_CN.GB18030)
  18. epoch如何设置,在Keras中,steps_per_epoch和纪元的设置如何影响训练结果?
  19. UCB——上界置信算法
  20. Word太大怎么进行压缩?实用Word压缩工具

热门文章

  1. ImportError: libpq.so.5: cannot open shared object file: No such file or directory
  2. SharePoint 2010 - 如何导入\导出WebPart
  3. [转]常用Delphi开发资料网址
  4. 扫描java类文件_java递归与非递归实现扫描文件夹下文件的实例代码
  5. hinton教授的本科生课程CSC321-机器学习中的神经网的笔记
  6. CS Academy Gcd Rebuild
  7. 配置FTP服务2(vsftpd 配置虚拟账号)
  8. 个人控件/对象命名规范(慢慢更新)
  9. UrlRewrite(Url重写技术)
  10. jquery 使用方法