OpenAPI規范是描述API功能的文檔,該文檔的的信息基於控制器和模型中的XML屬性注釋。它也是OpenAPI流的核心部分,用於驅動SwaggerUI之類的工具。一般命名為openapi.json
下面是為簡潔起見而縮減的 OpenAPI 規范的示例:
{ "openapi": "3.0.1", "info": { "title": "API V1", "version": "v1" }, "paths": { "/api/Todo": { "get": { "tags": [ "Todo" ], "operationId": "ApiTodoGet", "responses": { "200": { "description": "Success", "content": { "text/plain": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/ToDoItem" } } }, "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/ToDoItem" } } }, "text/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/ToDoItem" } } } } } } }, "post": { … } }, "/api/Todo/{id}": { "get": { … }, "put": { … }, "delete": { … } } }, "components": { "schemas": { "ToDoItem": { "type": "object", "properties": { "id": { "type": "integer", "format": "int32" }, "name": { "type": "string", "nullable": true }, "isCompleted": { "type": "boolean" } }, "additionalProperties": false } } } }
SwaggerUI 提供了基於 Web 的 UI,它使用生成的 OpenAPI 規范提供有關服務的信息。
Swashbuckle 有三個主要組成部分:
- Swagger: 將 SwaggerDocument 對象公開為 Json 終結點的Swagger對象模型和中間件。以便於我們對文檔內容的設置,和中間件的調用。
- SwaggerGen:從路由、控制器和模型直接生成 SwaggerDocument 對象的 Swagger 生成器。 它通常與 Swagger 終結點中間件結合,以自動公開 Swagger JSON。 這樣我們在編寫API時,Swagger便會自動識別我們的API並加入SwaggerDocument。公開到UI。
- SwaggerUI:Swagger UI 工具的嵌入式版本。它解釋了Swagger Json文檔來生成具有我們描述性的Web API,還具有對公共方法的內置測試工具。
我們引入NuGet工具包時,選擇最新的“Swashbuckle.AspNetCore”包。然后配置Swagger中間件和服務:
中間件:
我們需要添加Swagger中間件將SwaggerDocument文檔暴露出,然后使用SwaggerUI中間件解釋 SwaggerDocument 來生成具有描述性的Web API,並指定我們要暴露的 Swagger Json endpoint。
注意UseSwaggerUI方法調用啟用了UseStaticFile中間件。在一些 UseStaticFile 會影響的中間件出現時,需要考慮中間件的引用順序。
所以大概是這個樣子:
app.UseSwagger();
app.UseStatciFile(); //useSwaggerUI自動引入 app.UseSwaggerUI(options => { //暴露Json文檔終結點 options.SwaggerEndpoint("/swagger/v1/swagger.json", "Api V1");
}); app.UseRouting(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); });
可在 http://localhost:<port>/swagger
找到 Swagger UI。 通過 Swagger UI 瀏覽 API。要在應用的根 (http://localhost:<port>/
) 處提供 Swagger UI,請將 RoutePrefix
屬性設置為空字符串:
app.UseSwaggerUI(c => { c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1"); c.RoutePrefix = string.Empty; });
服務:
將SwaggerGen注冊在服務中,便可以將控制器的公共方法和模型的信息生成到SwaggerDocument中以便於暴露至Web UI,另外我們可以額外的指定信息:
傳遞給 AddSwaggerGen
方法的配置操作會添加諸如作者、許可證和說明的信息:使用 OpenApiInfo
類修改 UI 中顯示的信息:
services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo() { Version = "v1", Title = "Xieyi API", Description = "xieyi's simple example ASP.NET Core Web API", TermsOfService = new Uri("https://www.baidu.com"), Contact = new OpenApiContact { Name = "Zhou Xieyi", Email = "zhouxieyi@qq.com", Url = new Uri("https://www.sina.com.cn") }, License = new OpenApiLicense { Name = "Go to Learn Swashbuckle", Url = new Uri("https://docs.microsoft.com/zh-cn/aspnet/core/tutorials/getting-started-with-swashbuckle?view=aspnetcore-5.0&tabs=visual-studio") } });
});
效果展示:
啟用XML注釋,反射用於生成與 Web API 項目相匹配的 XML 文件名。 AppContext.BaseDirectory屬性用於構造 XML 文件的路徑。 一些 Swagger 功能(例如,輸入參數的架構,或各自屬性中的 HTTP 方法和響應代碼)無需使用 XML 文檔文件即可起作用。
var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile); c.IncludeXmlComments(xmlPath);
Tips:若啟動時,出現不能發現XML文檔,則是沒有生成,檢查此處。項目屬性中。
對於大多數功能(即方法摘要以及參數說明和響應代碼說明),必須使用 XML 文件。
<remarks> 元素可提供我們自定義的指定信息,提供更加可靠的Swagger UI,比如我們認為POST方法中ExameValue不夠具體,我們可以自定義我們的備注提供給SwaggerUI:
/// <summary> /// Creates a TodoItem. /// </summary> /// <remarks> /// Sample request: /// /// POST /Todo /// { /// "id": 1, /// "name": "Item1", /// "isCompleted": true /// } /// </remarks> /// <param name="item">model to add</param> /// <returns></returns>
效果圖:
我們可以對模型進行必填特性來改變Json中的架構,並可以自定義規定響應內容類型:
[Produces("application/json")] [Route("api/[controller]")] [ApiController] public class TodoController : ControllerBase { private readonly TodoContext _context;
描述響應類型:
在我們進行POST操作時,通常會判斷模型是否為null,若為null則返回400,但文檔描述中可能只有我們返回的200狀態碼,那么就會使使用者對我們的API描述不夠全面。我們可以自己規定響應類型和錯誤代碼。
/// <summary> /// Creates a TodoItem. /// </summary> /// <remarks> /// Sample request: /// /// POST /Todo /// { /// "id": 1, /// "name": "Item1", /// "isComplete": true /// } /// /// </remarks> /// <param name="item"></param> /// <returns>A newly created TodoItem</returns> /// <response code="201">Returns the newly created item</response> /// <response code="400">If the item is null</response> [HttpPost] [ProducesResponseType(StatusCodes.Status201Created)] [ProducesResponseType(StatusCodes.Status400BadRequest)] public ActionResult<TodoItem> Create(TodoItem item) { _context.TodoItems.Add(item); _context.SaveChanges(); return CreatedAtRoute("GetTodo", new { id = item.Id }, item); }
Swagger UI 現在清楚地記錄預期的 HTTP 響應代碼: