【动态Web API学习(三)】动态方法

news/2024/10/2 14:35:28

1.应用程序模型

ASP.NET Core MVC根据控制器、操作、操作参数、路由和筛选器的结果,定义模型如下:
ApplicationModel、控制器(ControllerModel)、操作(ActionModel)和参数(ParameterModel)。

上一节中只是告诉系统封哪个是控制器,还要为控制器模型初始化值,比如路由、请求方式(post、get)、方法名,才可以真正实现动态Web API。

2.动态方法实现

2.1 添加AutoApplicationModelConvention

在项目Flavor.AutoWebAPICore,添加AutoApplicationModelConvention。
image

2.2 AutoApplicationModelConvention代码

AutoApplicationModelConvention
using System.Text;
using Flavor.AutoWebAPICore;
using Microsoft.AspNetCore.Mvc.ActionConstraints;
using Microsoft.AspNetCore.Mvc.ApplicationModels;namespace Flavor.AutoWebAPICore
{/// <summary>/// 自动控制器应用模型/// </summary>public class AutoApplicationModelConvention : IApplicationModelConvention{/// <summary>/// 控制器移除的后缀/// </summary>private readonly string _ControllerRemoveSuffix = "AppService";public void Apply(ApplicationModel application){//遍历控制器foreach (var controller in application.Controllers){var type = controller.ControllerType;//设置控制器名称if (controller.ControllerName.EndsWith(_ControllerRemoveSuffix)){controller.ControllerName = controller.ControllerName[..^_ControllerRemoveSuffix.Length];}//控制器继承于IAutoControllerif (typeof(IAutoController).IsAssignableFrom(type)){//设置API对外可见ConfigureApiExplorer(controller);//设置控制器选择器ConfigureSelector(controller);}}}/// <summary>/// 设置API对外可见/// </summary>/// <param name="controller"></param>private static void ConfigureApiExplorer(ControllerModel controller){if (!controller.ApiExplorer.IsVisible.HasValue){controller.ApiExplorer.IsVisible = true;}foreach (var action in controller.Actions){if (!action.ApiExplorer.IsVisible.HasValue){action.ApiExplorer.IsVisible = true;}}}/// <summary>/// 设置控制器选择器/// </summary>/// <param name="controller"></param>private void ConfigureSelector(ControllerModel controller){//移除空的选择器RemoveEmptySelectors(controller.Selectors);if (controller.Selectors.Any(selector => selector.AttributeRouteModel != null)){return;}//遍历控制器的方法foreach (var action in controller.Actions){//设置方法的选择器ConfigureSelector(action);}}/// <summary>/// 移除空的选择器/// </summary>/// <param name="selectors"></param>private static void RemoveEmptySelectors(IList<SelectorModel> selectors){for (var i = selectors.Count - 1; i >= 0; i--){var selector = selectors[i];if (selector.AttributeRouteModel == null &&(selector.ActionConstraints == null || selector.ActionConstraints.Count <= 0) &&(selector.EndpointMetadata == null || selector.EndpointMetadata.Count <= 0)){selectors.Remove(selector);}}}/// <summary>/// 设置方法的选择器/// </summary>/// <param name="action"></param>private void ConfigureSelector(ActionModel action){RemoveEmptySelectors(action.Selectors);if (action.Selectors.Count <= 0){//添加选择器AddServiceSelector(action);}else{//格式化选择器NormalizeSelectorRoutes(action);}}/// <summary>/// 为方法添加选择器:路由、Http请求方式/// </summary>/// <param name="action"></param>private void AddServiceSelector(ActionModel action){var httpMothod = GetHttpMethod(action);var template = new Microsoft.AspNetCore.Mvc.RouteAttribute(GetRouteTemplate(action));var selector = new SelectorModel{AttributeRouteModel = new AttributeRouteModel(template)};selector.ActionConstraints.Add(new HttpMethodActionConstraint(new[] { httpMothod }));action.Selectors.Add(selector);}/// <summary>/// 格式化方法选择器:路由、Http请求方式/// </summary>/// <param name="action"></param>private void NormalizeSelectorRoutes(ActionModel action){foreach (var selector in action.Selectors){var httpMothod = GetHttpMethod(action);if (selector.AttributeRouteModel == null){var template = new Microsoft.AspNetCore.Mvc.RouteAttribute(GetRouteTemplate(action));selector.AttributeRouteModel = new AttributeRouteModel(template);}if (selector.ActionConstraints.OfType<HttpMethodActionConstraint>().FirstOrDefault()?.HttpMethods?.FirstOrDefault() == null){selector.ActionConstraints.Add(new HttpMethodActionConstraint(new[] { httpMothod }));}}}/// <summary>/// 获取路由/// </summary>/// <param name="action"></param>/// <returns></returns>private string GetRouteTemplate(ActionModel action){//路由var routeTemplate = new StringBuilder();// 控制器var controllerName = action.Controller.ControllerName;if (controllerName.EndsWith(_ControllerRemoveSuffix)){controllerName = controllerName[0..^_ControllerRemoveSuffix.Length];}routeTemplate.Append($"/{controllerName}");// 方法var actionName = action.ActionName;if (!string.IsNullOrEmpty(actionName)){routeTemplate.Append($"/{actionName}");}return routeTemplate.ToString();}/// <summary>/// 获取请求方式/// </summary>/// <param name="action"></param>/// <returns></returns>private static string GetHttpMethod(ActionModel action){var actionName = action.ActionName;if (actionName.StartsWith("Get")){return "Get";}else if (actionName.StartsWith("Put")){return "Put";}else if (actionName.StartsWith("Delete")){return "Delete";}else if (actionName.StartsWith("Options")){return "Options";}else if (actionName.StartsWith("Trace")){return "Trace";}else if (actionName.StartsWith("Head")){return "Head";}else if (actionName.StartsWith("Patch")){return "Patch";}return "Post";}}
}

代码说明:
1、AutoApplicationModelConvention继承IApplicationModelConvention,并实现接口:apply绑定控制器、方法模型。
2、其中方法:ConfigureApiExplorer,设置控制器、方法对外可见。通过设置属性:ApiExplorer。在Asp.net core中,API默认对外可见,如果没设置也可以。
3、方法:ConfigureSelector,用于初始化路由、Http请求方法。

2.3 添加动态方法

在Program.cs项目入口,添加动态方法。

Program.cs
//添加动态方法
builder.Services.AddMvc(m =>
{m.Conventions.Add(new AutoApplicationModelConvention());
});

image

2.4 测试

测试效果如下:
1、控制器名称,路由名称都已去掉后缀:AppService。
2、接口正常请求结果。
3、请求方法为Get。
image

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/67098.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

关于Arch Linux 安装及一些相关问题总结

关于个人Arch Linux 安装及相关问题总结 0. 其它记得在pacstrap前换国内的源 不会有人和我一样没换等半天还不成功吧 😦交换分区开大一点,照着Windows下开(看taskmgr里面的缓存空间),比如4G的RAM就要开10G的swap,swap越大越不容易卡死,安装时用swapon启用你刚建的swap…

深度学习(可视化卷积核)

可视化卷积核参数对理解卷积神经网络的工作原理、优化模型性能、提高模型泛化能力有一定帮助作用。 下面以resnet18为例,可视化了部分卷积核参数。import torchvision from matplotlib import pyplot as plt import torchmodel = torchvision.models.resnet18(pretrained=True…

《痞子衡嵌入式半月刊》 第 108 期

痞子衡嵌入式半月刊: 第 108 期这里分享嵌入式领域有用有趣的项目/工具以及一些热点新闻,农历年分二十四节气,希望在每个交节之日准时发布一期。 本期刊是开源项目(GitHub: JayHeng/pzh-mcu-bi-weekly),欢迎提交 issue,投稿或推荐你知道的嵌入式那些事儿。 上期回顾 :《…

痞子衡嵌入式半月刊: 第 108 期

痞子衡嵌入式半月刊: 第 108 期这里分享嵌入式领域有用有趣的项目/工具以及一些热点新闻,农历年分二十四节气,希望在每个交节之日准时发布一期。 本期刊是开源项目(GitHub: JayHeng/pzh-mcu-bi-weekly),欢迎提交 issue,投稿或推荐你知道的嵌入式那些事儿。 上期回顾 :《…

57_初识搜索引擎_分布式搜索引擎内核解密之query phase

1、query phase (1)搜索请求发送到某一个coordinate node,构构建一个priority queue,长度以paging操作from和size为准,默认为10 (2)coordinate node将请求转发到所有shard,每个shard本地搜索,并构建一个本地的priority queue (3)各个shard将自己的priority queue返回…

(六)WPF数据驱动模式

WPF开发方式; MVVM(Model View ViewModel)1.绑定XAML数据方式 在 XAML中添加绑定数据和绑定的操作属性 Content="{Binding MyVar}"  在XAML对应了的窗体类的构造函数添加数据绑定 this.DataContext = mainViewModel; //让此页面的数据取MainView…

[半成品]群晖cups链接打印机

本文是半成品, 仅提供思路. 不保证能完全成功 (因为我就没成功, USB 识别不了) 本文基于 github 开源项目以及 docker 关闭群晖自带的 cups 群晖是自带 cups, 你只需要把 USB 接口链接打印机后, 即可在控制面板->外接设备, 链接即可 我的由于不知名的原因压根识别不到, 所以…

AI+明厨亮灶解决方案

AI+明厨亮灶解决方案通过AI视觉分析算法,AI+明厨亮灶解决方案可接入现场已有的监控摄像头运行多种主流算法,AI+明厨亮灶解决方案可以对后厨实现如口罩识别、厨师服穿戴、夜间老鼠监测、厨师帽识别、厨师玩手机打电话识别、抽烟识别等。AI+明厨亮灶解决方案通过视频智能分析技…