در قسمت قبل موفق شدیم بر اساس OpenAPI specification endpoint تنظیم شده، رابط کاربری خودکاری را توسط ابزار Swagger-UI تولید کنیم. در ادامه میخواهیم این مستندات تولید شده را غنیتر کرده و کیفیت آنرا بهبود دهیم.
استفاده از XML Comments برای بهبود کیفیت مستندات API
نوشتن توضیحات XML ای برای متدها و پارامترها در پروژههای داتنتی، روشی استاندارد و شناخته شدهاست. برای نمونه در AuthorsController، میخواهیم توضیحاتی را به اکشن متد GetAuthor آن اضافه کنیم:
در این حالت اگر برنامه را اجرا کنیم، این توضیحات XMLای هیچ تاثیری را بر روی OpenAPI specification تولیدی و در نهایت Swagger-UI تولید شدهی بر اساس آن، نخواهد داشت. برای رفع این مشکل، باید به فایل OpenAPISwaggerDoc.Web.csproj مراجعه نمود و تولید فایل XML متناظر با این توضیحات را فعال کرد:
پس از تنظیم خاصیت GenerateDocumentationFile به true، با هر بار Build برنامه، فایل xml ای مطابق نام اسمبلی برنامه، در پوشهی bin آن تشکیل خواهد شد؛ مانند فایل bin\Debug\netcoreapp2.2\OpenAPISwaggerDoc.Web.xml در این مثال.
اکنون نیاز است وجود این فایل را به تنظیمات SwaggerDoc در کلاس Startup برنامه، اعلام کنیم:
در متد IncludeXmlComments، بجای ذکر صریح نام و مسیر فایل OpenAPISwaggerDoc.Web.xml، بر اساس نام اسمبلی جاری، نام فایل XML مستندات تعیین و مقدار دهی شدهاست.
پس از این تنظیمات اگر برنامه را اجرا کنیم، در Swagger-UI حاصل، این تغییرات قابل مشاهده هستند:
افزودن توضیحات به Response
تا اینجا توضیحات پارامترها و متدها را افزودیم؛ اما response از نوع 200 آن هنوز فاقد توضیحات است:
علت را نیز در تصویر فوق مشاهده میکنید. قسمت responses در OpenAPI specification، اطلاعات خودش را از اسکیمای مدلهای مرتبط دریافت میکند. بنابراین نیاز است کلاس DTO متناظر با Author را به نحو ذیل تکمیل کنیم:
مشکل! در این حالت اگر برنامه را اجرا کنیم، خروجی این توضیحات را در قسمت schemas مشاهده نخواهیم کرد. علت اینجا است که چون اسمبلی OpenAPISwaggerDoc.Models با اسمبلی OpenAPISwaggerDoc.Web یکی نیست و آنرا از پروژهی اصلی خارج کردهایم، به همین جهت نیاز است ابتدا به فایل OpenAPISwaggerDoc.Models.csproj مراجعه و GenerateDocumentationFile آنرا فعال کرد:
سپس باید فایل xml مستندات آنرا به صورت مجزایی به تنظیمات ابتدایی برنامه معرفی نمود:
با توجه به اینکه تمام فایلهای xml تولید شده در آخر به پوشهی bin\Debug\netcoreapp2.2 کپی میشوند، فقط کافی است حلقهای را تشکیل داده و تمام آنها را یکی یکی توسط متد IncludeXmlComments به تنظیمات AddSwaggerGen اضافه کرد.
در این حالت اگر مجددا برنامه را اجرا کنیم، خروجی ذیل را در قسمت schemas مشاهده خواهیم کرد:
بهبود مستندات به کمک Data Annotations
اگر به اکشن متد UpdateAuthor در کنترلر نویسندگان دقت کنیم، چنین امضایی را دارد:
جائیکه موجودیت Author را در پروژهی OpenAPISwaggerDoc.Entities تعریف کردهایم، نام و نام خانوادگی اجباری بوده و دارای حداکثر طول 150 حرف، هستند. قصد داریم همین ویژگیها را به DTO دریافتی این متد، یعنی AuthorForUpdate نیز اعمال کنیم:
پس از افزودن ویژگیهای Required و MaxLength به این DTO، خروجی Sawgger-UI به صورت زیر بهبود پیدا میکند:
بهبود مستندات متد HttpPatch با ارائهی یک مثال
دو نگارش از اکشن متد UpdateAuthor در این مثال موجود هستند:
یکی HttpPut است
و دیگری HttpPatch:
این مورد آرام آرام در حال تبدیل شدن به یک استاندارد است؛ چون امکان Partial updates را فراهم میکند. به همین جهت نسبت به HttpPut، کارآیی بهتری را ارائه میدهد. اما چون پارامتر دریافتی آن از نوع ویژهی JsonPatchDocument است و مثال پیشفرض مستندات آن، آنچنان مفهوم نیست:
بهتر است در این حالت مثالی را به استفاده کنندگان از آن ارائه دهیم تا در حین کار با آن، به مشکل برنخورند:
در اینجا در حین کامنت نویسی، میتوان از المان remarks، برای نوشتن توضیحات اضافی مانند ارائهی یک مثال، استفاده کرد که در آن op و path معادلهای بهتری را نسبت به مستندات پیشفرض آن پیدا کردهاند. در اینجا برای ذکر خطوط جدید باید از \ استفاده کرد؛ وگرنه خروجی نهایی، در یک سطر نمایش داده میشود:
روش کنترل warningهای کامنتهای تکمیل نشده
با فعالسازی GenerateDocumentationFile در فایل csproj برنامه، کامپایلر، بلافاصله برای تمام متدها و خواص عمومی که دارای کامنت نیستند، یک warning را صادر میکند. یک روش برطرف کردن این مشکل، افزودن کامنت به تمام قسمتهای برنامه است. روش دیگر آن، تکمیل خواص کامپایلر، جهت مواجه شدن با عدم وجود کامنتها در فایل csproj برنامه است:
توضیحات:
- اگر میخواهید خودتان را مجبور به کامنت نویسی کنید، میتوانید نبود کامنتها را تبدیل به error کنید. برای این منظور خاصیت TreatWarningsAsErrors را به true تنظیم کنید. در این حالت هر کامنت نوشته نشده، به صورت یک error توسط کامپایلر گوشزد شده و برنامه کامپایل نخواهد شد.
- اگر TreatWarningsAsErrors را خاموش کردید، هنوز هم میتوانید یکسری از warningهای انتخابی را تبدیل به error کنید. برای مثال NU1605 ذکر شدهی در خاصیت WarningsAsErrors، مربوط به package downgrade detection warning است.
- اگر به warning نبود کامنتها دقت کنیم به صورت عبارات warning CS1591: Missing XML comment for publicly visible type or member شروع میشود. یعنی CS1591 مربوط به کامنتهای نوشته نشدهاست. میتوان برای صرفنظر کردن از آن، شمارهی این خطا را بدون CS، توسط خاصیت NoWarn ذکر کرد.
کدهای کامل این قسمت را از اینجا میتوانید دریافت کنید: OpenAPISwaggerDoc-03.zip
در قسمت بعد، مشکل خروجی تولید response از نوع 200 را که در قسمت دوم به آن اشاره کردیم، بررسی خواهیم کرد.
استفاده از XML Comments برای بهبود کیفیت مستندات API
نوشتن توضیحات XML ای برای متدها و پارامترها در پروژههای داتنتی، روشی استاندارد و شناخته شدهاست. برای نمونه در AuthorsController، میخواهیم توضیحاتی را به اکشن متد GetAuthor آن اضافه کنیم:
/// <summary> /// Get an author by his/her id /// </summary> /// <param name="authorId">The id of the author you want to get</param> /// <returns>An ActionResult of type Author</returns> [HttpGet("{authorId}")] public async Task<ActionResult<Author>> GetAuthor(Guid authorId)
<Project Sdk="Microsoft.NET.Sdk.Web"> <PropertyGroup> <TargetFramework>netcoreapp2.2</TargetFramework> <AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel> <GenerateDocumentationFile>true</GenerateDocumentationFile> </PropertyGroup>
اکنون نیاز است وجود این فایل را به تنظیمات SwaggerDoc در کلاس Startup برنامه، اعلام کنیم:
namespace OpenAPISwaggerDoc.Web { public class Startup { public void ConfigureServices(IServiceCollection services) { services.AddSwaggerGen(setupAction => { setupAction.SwaggerDoc( // ... ); var xmlCommentsFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; var xmlCommentsFullPath = Path.Combine(AppContext.BaseDirectory, xmlCommentsFile); setupAction.IncludeXmlComments(xmlCommentsFullPath); }); }
پس از این تنظیمات اگر برنامه را اجرا کنیم، در Swagger-UI حاصل، این تغییرات قابل مشاهده هستند:
افزودن توضیحات به Response
تا اینجا توضیحات پارامترها و متدها را افزودیم؛ اما response از نوع 200 آن هنوز فاقد توضیحات است:
علت را نیز در تصویر فوق مشاهده میکنید. قسمت responses در OpenAPI specification، اطلاعات خودش را از اسکیمای مدلهای مرتبط دریافت میکند. بنابراین نیاز است کلاس DTO متناظر با Author را به نحو ذیل تکمیل کنیم:
using System; namespace OpenAPISwaggerDoc.Models { /// <summary> /// An author with Id, FirstName and LastName fields /// </summary> public class Author { /// <summary> /// The id of the author /// </summary> public Guid Id { get; set; } /// <summary> /// The first name of the author /// </summary> public string FirstName { get; set; } /// <summary> /// The last name of the author /// </summary> public string LastName { get; set; } } }
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFramework>netstandard2.0</TargetFramework> <GenerateDocumentationFile>true</GenerateDocumentationFile> </PropertyGroup> </Project>
namespace OpenAPISwaggerDoc.Web { public class Startup { public void ConfigureServices(IServiceCollection services) { services.AddSwaggerGen(setupAction => { setupAction.SwaggerDoc( // ... ); var xmlFiles = Directory.GetFiles(AppContext.BaseDirectory, "*.xml", SearchOption.TopDirectoryOnly).ToList(); xmlFiles.ForEach(xmlFile => setupAction.IncludeXmlComments(xmlFile)); }); }
در این حالت اگر مجددا برنامه را اجرا کنیم، خروجی ذیل را در قسمت schemas مشاهده خواهیم کرد:
بهبود مستندات به کمک Data Annotations
اگر به اکشن متد UpdateAuthor در کنترلر نویسندگان دقت کنیم، چنین امضایی را دارد:
[HttpPut("{authorId}")] public async Task<ActionResult<Author>> UpdateAuthor(Guid authorId, AuthorForUpdate authorForUpdate)
using System.ComponentModel.DataAnnotations; namespace OpenAPISwaggerDoc.Models { /// <summary> /// An author for update with FirstName and LastName fields /// </summary> public class AuthorForUpdate { /// <summary> /// The first name of the author /// </summary> [Required] [MaxLength(150)] public string FirstName { get; set; } /// <summary> /// The last name of the author /// </summary> [Required] [MaxLength(150)] public string LastName { get; set; } } }
بهبود مستندات متد HttpPatch با ارائهی یک مثال
دو نگارش از اکشن متد UpdateAuthor در این مثال موجود هستند:
یکی HttpPut است
[HttpPut("{authorId}")] public async Task<ActionResult<Author>> UpdateAuthor(Guid authorId, AuthorForUpdate authorForUpdate)
[HttpPatch("{authorId}")] public async Task<ActionResult<Author>> UpdateAuthor( Guid authorId, JsonPatchDocument<AuthorForUpdate> patchDocument)
بهتر است در این حالت مثالی را به استفاده کنندگان از آن ارائه دهیم تا در حین کار با آن، به مشکل برنخورند:
/// <summary> /// Partially update an author /// </summary> /// <param name="authorId">The id of the author you want to get</param> /// <param name="patchDocument">The set of operations to apply to the author</param> /// <returns>An ActionResult of type Author</returns> /// <remarks> /// Sample request (this request updates the author's first name) \ /// PATCH /authors/id \ /// [ \ /// { \ /// "op": "replace", \ /// "path": "/firstname", \ /// "value": "new first name" \ /// } \ /// ] \ /// </remarks> [HttpPatch("{authorId}")] public async Task<ActionResult<Author>> UpdateAuthor( Guid authorId, JsonPatchDocument<AuthorForUpdate> patchDocument)
روش کنترل warningهای کامنتهای تکمیل نشده
با فعالسازی GenerateDocumentationFile در فایل csproj برنامه، کامپایلر، بلافاصله برای تمام متدها و خواص عمومی که دارای کامنت نیستند، یک warning را صادر میکند. یک روش برطرف کردن این مشکل، افزودن کامنت به تمام قسمتهای برنامه است. روش دیگر آن، تکمیل خواص کامپایلر، جهت مواجه شدن با عدم وجود کامنتها در فایل csproj برنامه است:
<Project Sdk="Microsoft.NET.Sdk.Web"> <PropertyGroup> <TargetFramework>netcoreapp2.2</TargetFramework> <AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel> <GenerateDocumentationFile>true</GenerateDocumentationFile> <TreatWarningsAsErrors>false</TreatWarningsAsErrors> <WarningsAsErrors>NU1605;</WarningsAsErrors> <NoWarn>1701;1702;1591</NoWarn> </PropertyGroup>
- اگر میخواهید خودتان را مجبور به کامنت نویسی کنید، میتوانید نبود کامنتها را تبدیل به error کنید. برای این منظور خاصیت TreatWarningsAsErrors را به true تنظیم کنید. در این حالت هر کامنت نوشته نشده، به صورت یک error توسط کامپایلر گوشزد شده و برنامه کامپایل نخواهد شد.
- اگر TreatWarningsAsErrors را خاموش کردید، هنوز هم میتوانید یکسری از warningهای انتخابی را تبدیل به error کنید. برای مثال NU1605 ذکر شدهی در خاصیت WarningsAsErrors، مربوط به package downgrade detection warning است.
- اگر به warning نبود کامنتها دقت کنیم به صورت عبارات warning CS1591: Missing XML comment for publicly visible type or member شروع میشود. یعنی CS1591 مربوط به کامنتهای نوشته نشدهاست. میتوان برای صرفنظر کردن از آن، شمارهی این خطا را بدون CS، توسط خاصیت NoWarn ذکر کرد.
کدهای کامل این قسمت را از اینجا میتوانید دریافت کنید: OpenAPISwaggerDoc-03.zip
در قسمت بعد، مشکل خروجی تولید response از نوع 200 را که در قسمت دوم به آن اشاره کردیم، بررسی خواهیم کرد.