ใส่ Swagger ให้กับ .NET Core API

swagger เป็น tool เอาไว้สำหรับสร้าง document สำหรับ API แถมว่า document ที่สร้างขึ้นมา มันทำหน้าที่เป็น testing tool เพื่อใช้ทดสอบ API นั้นให้ได้อีกด้วย คือเรียกได้ว่า โคตรมหาเทพ tool กันเลยทีเดียว

ตัว swagger เอง มัน support หลาย ๆ ภาษา .NET Core เป็นหนึ่งในนั้น วิธีการใช้งานก็ไม่ยากอะไร (เท่าที่ลอง) เลยเอามาจดไว้หน่อย เดี๋ยวลืม

เริ่มจาก add package เข้ามาใน web api project ก่อน

dotnet add MyService/MyService.csproj package Swashbuckle.AspNetCore

เสร็จแล้ว เข้าไปแก้ method ConfigureServices ในไฟล์ Startup.cs เพิ่ม .AddSwaggerGen ลงไปตามนี้

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();

    services.AddSwaggerGen(c => {
        c.SwaggerDoc("v1", new Info { Title = "My Service API", Version = "v1"});
    });
}

เสร็จแล้วแก้ method Configure ในไฟล์เดิม

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }

    app.UseSwagger();
    app.UseSwaggerUI(c => {
        c.SwaggerEndpoint("/swagger/v1/swagger.json", "My Service API v1");
    });

    app.UseMvc();
}

เสร็จแล้ว!!

ที่เหลือแค่ start api ของเรา

dotnet run

แล้วก็ลองเข้าไปที่ url http://localhost:5000/swagger

เราก็จะเห็น API Document แบบเท่ ๆ ของเรา ประมาณนี้ เท่ดีเนอะ

เดี๋ยวก่อน ยังไม่จบ!!

พอลองยิง request ดู มัน error เฉยเลย เพราะว่าจากในตัวอย่าง endpoint ของเราคือ /api/Pdf แต่ในความเป็นจริงที่กำหนดไว้คือ /api/pdf ตัวใหญ่ตัวเล็กต่างกัน ปัญหานี้เกิดจากชื่อ controller ที่มันตัดออกมา ชื่อ controller ที่ตั้งไว้ใน project คือ PdfController ทำให้มันกลายเป็นแบบนี้ ใครที่เผลอเข้ามาอ่าน แล้วเจอปัญหาเดียวกัน วิธีแก้ไขคือ ใช้ LowercaseDocumentFilter.cs ตามข้างล่างนี้

using System.Collections.Generic;
using Swashbuckle.AspNetCore.Swagger;
using Swashbuckle.AspNetCore.SwaggerGen;

namespace BoundedContext.Web.Swagger
{
    public class LowercaseDocumentFilter : IDocumentFilter
    {
        public void Apply(SwaggerDocument swaggerDoc, DocumentFilterContext context)
        {
            ////////    PATHS

            var paths = swaggerDoc.Paths;

            //  generate the new keys
            var newPaths = new Dictionary<string, PathItem>();
            var removeKeys = new List<string>();
            foreach (var path in paths)
            {
                var newKey = path.Key.ToLower();
                if (newKey != path.Key)
                {
                    removeKeys.Add(path.Key);
                    newPaths.Add(newKey, path.Value);
                }
            }

            //  add the new keys
            foreach (var path in newPaths)
            {
                swaggerDoc.Paths.Add(path.Key, path.Value);
            }

            //  remove the old keys
            foreach (var key in removeKeys)
            {
                swaggerDoc.Paths.Remove(key);
            }
        }
    }
}

โค้ด filter ด้านบนเอามาจาก gist ตามที่อยู่ในอ้างอิง และมีแก้ using เพื่อให้รันผ่าน พอใส่เข้าไป ที่เหลือก็เข้าไปแก้ใน Startup.cs

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();

    services.AddSwaggerGen(c => {
        c.SwaggerDoc("v1", new Info { Title = "PDF Service API", Version = "v1"});
        c.DocumentFilter<LowercaseDocumentFilter>();
    });
}

เท่านี้ก็สามารถใช้โคตรมหาเทพ api document ได้แล้ว

อ้างอิง

Leave a Reply