ASP.NET Web Api 如何使用 Swagger 管理 API

news2024/11/25 15:37:34

image

前言

Swagger 是一个开源的框架,支持 OpenAPI 规范,可以根据 API 规范自动生成美观的、易于浏览的 API 文档页面,包括请求参数、响应示例等信息,并且,Swagger UI 提供了一个交互式的界面,可以帮助我们快速测试和调试 API,验证 API 的功能和正确性。

总的来说,Swagger 是一个强大的工具,可以帮助开发人员设计、构建和文档化 RESTful API,提高 API 的可读性、可维护性和互操作性,有了它,我们就可以更方便、更有效率地管理 API。

在 ASP.NET Core 中,已经内置了 Swagger,很方便就能使用。但在 ASP.NET 里,需要我们自己引用和配置才能使用它,下面通过一个 Step By Step 例子来看看 ASP.NET Web Api 如何使用 Swagger。

Step By Step 步骤

  1. 创建 .netframework webapi 项目

  2. 在项目上右键 - 项目属性 - 生成 - (输出)勾选 “XML文档文件"并填写自定义路径如"App_Data\apidoc.xml”

  3. Nuget 安装以下 Swagger 相关的两个包

    Swashbuckle

    Swagger.NET.UI(这个不装也可以)

  4. 创建 App_Start/SwaggerCacheProvider 辅助类,用于获取 xml 文件注释内容,留意注释

    using Swashbuckle.Swagger;
    using System;
    using System.Collections.Concurrent;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Web;
    using System.Xml;
    
    namespace SwaggerTest
    {
    	/// <summary>
    	/// 支持方法注释
    	/// </summary>
    	public class SwaggerCacheProvider : ISwaggerProvider
    	{
    		private readonly ISwaggerProvider _swaggerProvider;
    		private static ConcurrentDictionary<string, SwaggerDocument> _cache = new ConcurrentDictionary<string, SwaggerDocument>();
    		private readonly string _xmlPath;
    
    		/// <summary>
    		/// 构造方法
    		/// </summary>
    		/// <param name="swaggerProvider"></param>
    		/// <param name="xmlpath"></param>
    		public SwaggerCacheProvider(ISwaggerProvider swaggerProvider, string xmlpath)
    		{
    			_swaggerProvider = swaggerProvider;
    			_xmlPath = xmlpath;
    		}
    
    		/// <summary>
    		/// 生成 Swagger 文档,并存入缓存
    		/// </summary>
    		/// <param name="rootUrl"></param>
    		/// <param name="apiVersion"></param>
    		/// <returns></returns>
    		/// <exception cref="NotImplementedException"></exception>
    		public SwaggerDocument GetSwagger(string rootUrl, string apiVersion)
    		{
    			var cacheKey = string.Format("{0}_{1}", rootUrl, apiVersion);
    			// 只读取一次
    			if (!_cache.TryGetValue(cacheKey, out SwaggerDocument srcDoc))
    			{
    				srcDoc = _swaggerProvider.GetSwagger(rootUrl, apiVersion);
    
    				srcDoc.vendorExtensions = new Dictionary<string, object>
    				{
    					{ "ControllerDesc", GetControllerDesc() }
    				};
    				_cache.TryAdd(cacheKey, srcDoc);
    			}
    			return srcDoc;
    		}
    
    		/// <summary>
    		/// 从API文档中读取控制器描述
    		/// </summary>
    		/// <returns></returns>
    		private ConcurrentDictionary<string, string> GetControllerDesc()
    		{
    			ConcurrentDictionary<string, string> controllerDescDict = new ConcurrentDictionary<string, string>();
    			if (File.Exists(_xmlPath))
    			{
    				// 1. 加载生成 xml
    				XmlDocument xmldoc = new XmlDocument();
    				xmldoc.Load(_xmlPath);
    
    				// 2. 读取控制器方法注释内容
    				string[] arrPath;
    				int cCount = "Controller".Length;
    				foreach (XmlNode node in xmldoc.SelectNodes("//member"))
    				{
    					string type = node.Attributes["name"].Value;
    					if (type.StartsWith("T:"))
    					{
    						arrPath = type.Split('.');
    						string controllerName = arrPath[arrPath.Length - 1];
    						if (controllerName.EndsWith("Controller"))  //控制器
    						{
    							// 获取控制器注释
    							XmlNode summaryNode = node.SelectSingleNode("summary");
    							string key = controllerName.Remove(controllerName.Length - cCount, cCount);
    							if (summaryNode != null && !string.IsNullOrEmpty(summaryNode.InnerText) && !controllerDescDict.ContainsKey(key))
    							{
    								controllerDescDict.TryAdd(key, summaryNode.InnerText.Trim());
    							}
    						}
    					}
    				}
    			}
    			return controllerDescDict;
    		}
    	}
    }	
    
  5. 创建 Scripts\swagger.js,用于支持显示中文注释内容

    'use strict';
    window.SwaggerTranslator = {
    	_words: [],
    
    	translate: function () {
    		var $this = this;
    		$('[data-sw-translate]').each(function () {
    			$(this).html($this._tryTranslate($(this).html()));
    			$(this).val($this._tryTranslate($(this).val()));
    			$(this).attr('title', $this._tryTranslate($(this).attr('title')));
    		});
    	},
    
    	setControllerSummary: function () {
    		$.ajax({
    			type: "get",
    			async: true,
    			url: $("#input_baseUrl").val(),
    			dataType: "json",
    			success: function (data) {
    				var summaryDict = data.ControllerDesc;
    				var id, controllerName, strSummary;
    				$("#resources_container .resource").each(function (i, item) {
    					id = $(item).attr("id");
    					if (id) {
    						controllerName = id.substring(9);
    						strSummary = summaryDict[controllerName];
    						if (strSummary) {
    							$(item).children(".heading").children(".options").first().prepend('<li class="controller-summary" title="' + strSummary + '">' + strSummary + '</li>');
    						}
    					}
    				});
    			}
    		});
    	},
    	_tryTranslate: function (word) {
    		return this._words[$.trim(word)] !== undefined ? this._words[$.trim(word)] : word;
    	},
    
    	learn: function (wordsMap) {
    		this._words = wordsMap;
    	}
    };
    
    
    /* jshint quotmark: double */
    window.SwaggerTranslator.learn({
    	"Warning: Deprecated": "警告:已过时",
    	"Implementation Notes": "实现备注",
    	"Response Class": "响应类",
    	"Status": "状态",
    	"Parameters": "参数",
    	"Parameter": "参数",
    	"Value": "值",
    	"Description": "描述",
    	"Parameter Type": "参数类型",
    	"Data Type": "数据类型",
    	"Response Messages": "响应消息",
    	"HTTP Status Code": "HTTP 状态码",
    	"Reason": "原因",
    	"Response Model": "响应模型",
    	"Request URL": "请求 URL",
    	"Response Body": "响应体",
    	"Response Code": "响应码",
    	"Response Headers": "响应头",
    	"Hide Response": "隐藏响应",
    	"Headers": "头",
    	"Try it out!": "试一下!",
    	"Show/Hide": "显示/隐藏",
    	"List Operations": "显示操作",
    	"Expand Operations": "展开操作",
    	"Raw": "原始",
    	"can't parse JSON.  Raw result": "无法解析 JSON。原始结果",
    	"Model Schema": "模型架构",
    	"Model": "模型",
    	"apply": "应用",
    	"Username": "用户名",
    	"Password": "密码",
    	"Terms of service": "服务条款",
    	"Created by": "创建者",
    	"See more at": "查看更多:",
    	"Contact the developer": "联系开发者",
    	"api version": "api 版本",
    	"Response Content Type": "响应 Content Type",
    	"fetching resource": "正在获取资源",
    	"fetching resource list": "正在获取资源列表",
    	"Explore": "浏览",
    	"Show Swagger Petstore Example Apis": "显示 Swagger Petstore 示例 Apis",
    	"Can't read from server.  It may not have the appropriate access-control-origin settings.": "无法从服务器读取。可能没有正确设置 access-control-origin。",
    	"Please specify the protocol for": "请指定协议:",
    	"Can't read swagger JSON from": "无法读取 swagger JSON于",
    	"Finished Loading Resource Information. Rendering Swagger UI": "已加载资源信息。正在渲染 Swagger UI",
    	"Unable to read api": "无法读取 api",
    	"from path": "从路径",
    	"server returned": "服务器返回"
    });
    $(function () {
    	window.SwaggerTranslator.translate();
    	window.SwaggerTranslator.setControllerSummary();
    });	
    
  6. 右键 Scripts\swagger.js - 属性 - 生成操作 - 改为 “嵌入的资源”

  7. 打开并修改 App_Start\SwaggerConfig.cs(安装以上包后自动生成此文件),以下是修改后的完整代码

    using System.Web.Http;
    using WebActivatorEx;
    using SwaggerTest;
    using Swashbuckle.Application;
    using System.Reflection;
    
    [assembly: PreApplicationStartMethod(typeof(SwaggerConfig), "Register")]
    namespace SwaggerTest
    {
    	// 完整版 Swagger config 代码
    
    	/// <summary>
    	/// 配置 Swagger
    	/// </summary>
    	public class SwaggerConfig
    	{
    		/// <summary>
    		/// 注册
    		/// </summary>
    		public static void Register()
    		{
    			var thisAssembly = typeof(SwaggerConfig).Assembly;
    
    			GlobalConfiguration.Configuration
    				.EnableSwagger(c =>
    					{
    						//用于启用和设置Swagger的配置信息。
    						c.SingleApiVersion("v2", "测试 API 接口文档");
    						c.IncludeXmlComments($@"{System.AppDomain.CurrentDomain.BaseDirectory}\bin\SwaggerTest.xml");
    						//获取项目指定路径下xml文件
    						c.CustomProvider((defaultProvider) => new SwaggerCacheProvider(defaultProvider, $@"{System.AppDomain.CurrentDomain.BaseDirectory}\bin\SwaggerTest.xml"));
    					})
    				.EnableSwaggerUi(c =>
    					{
    						//用于启用UI界面上的东西。
    						//加载汉化的js文件,注意 swagger.js文件属性必须设置为“嵌入的资源”。 APIUI.Scripts.swagger.js依次是:项目名称->文件夹->js文件名 
    						c.InjectJavaScript(Assembly.GetExecutingAssembly(), "SwaggerTest.Scripts.swagger.js");
    					});
    		}
    	}
    }	
    
  8. 打开并注释掉 App_Start\SwaggerNet.cs 代码(安装以上包后自动生成此文件)

    using System;
    using System.IO;
    using System.Web;
    using System.Web.Http;
    using System.Web.Http.Description;
    using System.Web.Http.Dispatcher;
    using System.Web.Routing;
    using Swagger.Net;
    
    //[assembly: WebActivator.PreApplicationStartMethod(typeof(SwaggerTest.App_Start.SwaggerNet), "PreStart")]
    //[assembly: WebActivator.PostApplicationStartMethod(typeof(SwaggerTest.App_Start.SwaggerNet), "PostStart")]
    namespace SwaggerTest.App_Start 
    {
    	/// <summary>
    	/// Swagger Net 
    	/// </summary>
    	public static class SwaggerNet 
    	{
    		//public static void PreStart() 
    		//{
    		//    RouteTable.Routes.MapHttpRoute(
    		//        name: "SwaggerApi",
    		//        routeTemplate: "api/docs/{controller}",
    		//        defaults: new { swagger = true }
    		//    );            
    		//}
    		
    		//public static void PostStart() 
    		//{
    		//    var config = GlobalConfiguration.Configuration;
    
    		//    config.Filters.Add(new SwaggerActionFilter());
    			
    		//    try
    		//    {
    		//        config.Services.Replace(typeof(IDocumentationProvider),
    		//            new XmlCommentDocumentationProvider(HttpContext.Current.Server.MapPath("~/bin/SwaggerTest.XML")));
    		//    }
    		//    catch (FileNotFoundException)
    		//    {
    		//        throw new Exception("Please enable \"XML documentation file\" in project properties with default (bin\\SwaggerTest.XML) value or edit value in App_Start\\SwaggerNet.cs");
    		//    }
    		//}
    	}
    }	
    
  9. 至此,Swagger 配置就完成了,接着就可以运行看看效果了

测试

  • 配置完成后,直接运行项目,打开以下网址,即可看到效果
    https://localhost:44335/swagger/
    

其它

  • Swagger.NET.UI不是必要的,运行 SwaggerUI目录下面的 index 反而会出错

我是老杨,一个奋斗在一线的资深研发老鸟,让我们一起聊聊技术,聊聊人生。

都看到这了,求个点赞、关注、在看三连呗,感谢支持。

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

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

相关文章

本来还挺喜欢……

前阵子买了个天空星开发板&#xff0c;到手之后发觉不对劲。 之前我们玩玩开发板都是用的面包板的&#xff0c;就算是ESP那种比较宽的板子用两个面包板拼一下也勉强可以用。 但是天空星它的引脚是分为两组&#xff0c;每组有两排&#xff0c;如果我们还是直接使用面包板的话&a…

Pencils Protocol 提供层次化的 Staking,品牌升级不断

Pencils Protocol 是一个 Scroll 生态中的一个综合应用平台&#xff0c;在全新的品牌升级后(原为 Penpad)&#xff0c;其在原有的 LaunchPad 的基础上&#xff0c;进一步向收益聚合器、RWA 等板块进行全新的拓展。目前&#xff0c;Pencils Protocol 生态的整体功能板块包括 Lau…

Kubernetes——两万字超细致集群搭建平台规划

目录 前言——常见的K8S安装部署方式 一、Kubernetes平台规划 1.单Master集群架构 2.多Master集群架构 二、集群规划 1.服务器硬件配置推荐 2.操作系统初始化 2.1关闭防火墙 2.2关闭SElinux 2.3关闭Swap 2.4添加Hosts 2.5调整内核参数 2.5同步时间 三、集群搭建…

【每日刷题】Day39

【每日刷题】Day39 &#x1f955;个人主页&#xff1a;开敲&#x1f349; &#x1f525;所属专栏&#xff1a;每日刷题&#x1f34d; &#x1f33c;文章目录&#x1f33c; 1. 622. 设计循环队列 - 力扣&#xff08;LeetCode&#xff09; 2. 387. 字符串中的第一个唯一字符 - …

C++类细节,反汇编,面试题02

文章目录 2. 虚函数vs纯虚函数3. 重写vs重载vs隐藏3.1. 为什么C可以重载&#xff1f; 4. struct vs union4.1. 为什么要内存对齐&#xff1f; 5. static作用6. 空类vs空结构体6.1. 八个默认函数&#xff1a;6.2. 为什么空类占用1字节 7. const作用7.1 指针常量vs常量指针vs常量…

k8s v1.20二进制部署

目录 一、环境准备 二、操作系统初始化配置 2.1.关闭防火墙 ​编辑 2.2.关闭selinux 2.3.关闭swap 2.4.根据规划设置主机名 2.5在master添加hosts 2.6.调整内核参数 2.7.时间同步 三、部署 docker引擎 3.1.所有 node 节点部署docker引擎 四、部署 etcd 集群 4.1.…

【云计算小知识】云管理的作用是什么?

云计算已经成为推动企业数字化转型&#xff0c;提升运营效率的重要力量。而在这个过程中&#xff0c;云管理作为确保云计算环境稳定、高效运行的关键环节&#xff0c;其作用愈发凸显。今天我们小编就给大家详细介绍一下云管理的作用是什么&#xff1f; 云管理的作用是什么&…

找不到mfc140.dll是什么意思?四种高效率方法修复mfc140.dll文件

软件运行过程中的错误和问题偶尔会发生&#xff0c;这可能导致不便和工作效率的降低。其中一个常见的问题是“找不到 mfc140.dll”错误消息&#xff0c;这会阻止某些基于 Microsoft Visual Studio 2015 编写的应用程序运行。mfc140.dll 是一个重要的系统文件&#xff0c;今天我…

Whistle Web Debugging Proxy介绍及使用

大家好&#xff0c;今天继续给大家分享一款抓包工具&#xff0c;这款抓包工具是网页的形式&#xff0c;方便多人访问同时维护。Whistle Web Debugging Proxy是一个用于HTTP、HTTPS、WebSocket等网络协议的跨平台调试工具。它可以帮助开发者对网络请求进行捕捉、分析、修改和重定…

Spring Boot项目怎么集成Gitee登录

一、背景 现在的越来越多的项目&#xff0c;需要集成第三方系统进行登录。今天我们以Spring Boot项目集成Gitee为例&#xff0c;演示一下怎么使用Oauth2协议&#xff0c;集成第三方系统登录。 不了解oauth2的&#xff0c;可以看我之前的文章。Ouath2是怎么实现在第三方应用认…

Java入门基础学习笔记21——Scanner

在程序中接收用户通过键盘输入的数据&#xff1a; 需求&#xff1a; 请在程序中&#xff0c;提示用户通过键盘输入自己的姓名、年龄、并能在程序中收到这些信息&#xff0c;怎么解决&#xff1f; Java已经写好了实现程序&#xff0c;我们调用即可。 API&#xff1a;Applicat…

Linux---vim编辑器(续写)

5. vim正常模式命令集 插入模式 按「i」切换进入插入模式「insert mode」&#xff0c; 按“i”进入插入模式后是从光标当前位置开始输入文件&#xff1b; 按「a」进入插入模式后&#xff0c;是从目前光标所在位置的下一个位置开始输入文字&#xff1b; 按「o」进入插入模式…

APP未上架应用市场,微信商户如何快速开通APP支付

在移动互联网时代&#xff0c;APP作为企业服务用户的重要窗口&#xff0c;其支付功能的完善性直接关系到用户体验和企业的营收。然而&#xff0c;对于许多未上架应用市场的APP来说&#xff0c;如何快速开通微信APP支付功能成为了一个亟待解决的问题。本文将为您详细介绍在APP未…

MetaRTC-push推流客户端代码分析

本demo渲染使用opengl&#xff0c;音频采集使用alsa&#xff0c;视频采集使用v4l2/dev/video。 在设计多个平台时&#xff0c;MetaRTC的源码和google的c webrtc源码都使用了工厂模式的方法&#xff0c;比如以下不同平台的视频采集为例子。YangVideoCaptureLinux是实现linux平台…

将macOS系统安装到外置硬盘上教程

常常因为Mac昂贵的价格&#xff0c;我们会选择低容量的硬盘版本&#xff0c;造成很多大型游戏都安装不了的尴尬境地。今天&#xff0c;我们要探讨一个非常实用的话题&#xff1a;如何给你的Mac电脑扩容&#xff0c;通过将macOS系统安装到外置硬盘上。这对于希望提升存储空间但又…

基于GD32的简易数字示波器(5)- 软件_控制LED

这期记录的是项目实战&#xff0c;做一个简易的数字示波器。 教程来源于嘉立创&#xff0c;帖子主要做学习记录&#xff0c;方便以后查看。 本期主要介绍GPIO口的输入输出模式&#xff0c;使用其中的输出模式驱动LED。详细教程可观看下方链接。 2.2 LED控制实验 语雀 1、LE…

表征和基于结构的蛋白质工程:黄芪特异性皂苷乙酰转移酶-文献精读14

Characterization and structure-based protein engineering of a regiospecific saponin acetyltransferase from Astragalus membranaceus 表征和基于结构的蛋白质工程&#xff1a;黄芪特异性皂苷乙酰转移酶&#xff0c;一篇乙酰基转移酶文章精读分享~ 摘要 乙酰化有助于许…

一文入门DNS

概述 DNS是一个缩写&#xff0c;可以代表Domain Name System&#xff0c;域名系统&#xff0c;是互联网的一项基础服务。也可以代表Domain Name Server&#xff0c;域名服务器&#xff0c;是进行域名和与之相对应的IP地址相互转换的服务器。DNS协议则是用来将域名转换为IP地址…

pgbackrest 备份工具使用 postgresql

为啥我会使用pgbackrest进行备份&#xff1f;因为postgresql没有自带的差异备份工具。。。而我们在生产环境上&#xff0c;一般都需要用到差异备份或者增量备份。我们的备份策略基本是&#xff0c;1天1次完整备份&#xff0c;1个小时1次差异备份。如果只需要完整备份&#xff0…

基于SSM的理发店会员管理系统的设计和实现(有报告)。Javaee项目。ssm项目。

演示视频&#xff1a; 基于SSM的理发店会员管理系统的设计和实现&#xff08;有报告&#xff09;。Javaee项目。ssm项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构&#xff0…