Swagger の設定
ASP.NET Web API プロジェクトで Swagger を有効にし、API ドキュメントを自動生成するための設定方法を説明します。ここでは、Swashbuckle ライブラリを使用します。
1. 設定コード
以下は、Swagger の機能をカスタマイズするための C# コード例です。このコードは、Swagger の有効化、UI のカスタマイズ、XML ドキュメントの読み込み、非表示 API のフィルタリング、およびドキュメントのキャッシュを設定します。
using Swashbuckle.Application;
using Swashbuckle.Swagger;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web.Http;
using System.Web.Http.Description;
using System.Xml.Linq;
[assembly: PreApplicationStartMethod(typeof(SwaggerSetup), "Configure")]
namespace ApiProject
{
public class SwaggerSetup
{
public static void Configure()
{
if (!PublicConfig.EnableSwagger) // Swagger を有効にするかどうか
{
return;
}
var assembly = typeof(SwaggerSetup).Assembly;
GlobalConfiguration.Configuration
.EnableSwagger(c =>
{
c.SingleApiVersion("v1", "API ドキュメント");
// XML ドキュメントを含める
c.IncludeXmlComments(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "bin/ApiProject.XML"));
c.IncludeXmlComments(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "bin/Models.XML"));
c.IncludeXmlComments(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "bin/Common.XML"));
// 非表示 API を除外するフィルタを適用
c.DocumentFilter<ApiHideFilter>();
// カスタム Swagger プロバイダーでドキュメントをキャッシュ
c.CustomProvider((defaultProvider) => new CachedSwaggerProvider(defaultProvider));
})
.EnableSwaggerUi(c =>
{
c.DocumentTitle("API ドキュメント");
// カスタム JavaScript を注入して UI をローカライズ
c.InjectJavaScript(assembly, "ApiProject.Scripts.swagger_localization.js");
// API キー認証を有効化
c.EnableApiKeySupport("Authorization", "header");
});
}
/// <summary>
/// ドキュメントのキャッシュとコントローラーの説明を追加するカスタムプロバイダー
/// </summary>
public class CachedSwaggerProvider : ISwaggerProvider
{
private static readonly ConcurrentDictionary _cache = new ConcurrentDictionary();
private readonly ISwaggerProvider _innerProvider;
public CachedSwaggerProvider(ISwaggerProvider innerProvider)
{
_innerProvider = innerProvider;
}
public SwaggerDocument GetSwagger(string rootUrl, string apiVersion)
{
var cacheKey = $"{rootUrl}_{apiVersion}";
if (!_cache.TryGetValue(cacheKey, out SwaggerDocument document))
{
document = _innerProvider.GetSwagger(rootUrl, apiVersion);
document.vendorExtensions = new Dictionary { { "ControllerDesc", GetControllerDescriptions() } };
_cache.TryAdd(cacheKey, document);
}
return document;
}
/// <summary>
/// XML ドキュメントからコントローラーの説明を取得
/// </summary>
/// <returns>コントローラー名と説明の辞書</returns>
public static ConcurrentDictionary GetControllerDescriptions()
{
var descriptions = new ConcurrentDictionary();
var xmlPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "bin/ApiProject.XML");
if (File.Exists(xmlPath))
{
var doc = XDocument.Load(xmlPath);
foreach (var member in doc.Descendants("member").Where(m => m.Attribute("name")?.Value.StartsWith("T:") == true))
{
var name = member.Attribute("name")?.Value;
if (name != null && name.Contains("."))
{
var controllerName = name.Split('.').Last();
if (controllerName.EndsWith("Controller"))
{
var summary = member.Element("summary")?.Value?.Trim();
if (!string.IsNullOrEmpty(summary))
{
var key = controllerName.Replace("Controller", "");
descriptions.TryAdd(key, summary);
}
}
}
}
}
return descriptions;
}
}
}
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
public class ApiHideAttribute : Attribute { }
public class ApiHideFilter : IDocumentFilter
{
public void Apply(SwaggerDocument swaggerDoc, SchemaRegistry schemaRegistry, IApiExplorer apiExplorer)
{
foreach (var apiDescription in apiExplorer.ApiDescriptions)
{
if (apiDescription.GetControllerAndActionAttributes<ApiHideAttribute>().Any())
{
var path = "/" + apiDescription.RelativePath.Split('?')[0];
swaggerDoc.paths.Remove(path);
}
}
}
}
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class ApiGroupAttribute : Attribute
{
public string GroupName { get; }
public string Description { get; }
public ApiGroupAttribute(string groupName, string description)
{
GroupName = groupName;
Description = description;
}
}
}
2. UI のローカライズ
Swagger UI を日本語にローカライズするための JavaScript ファイルです。このファイルはプロジェクトに「埋め込みリソース」として追加する必要があります。
/// <summary>
/// UI を日本語に翻訳
/// </summary>
var SwaggerLocalizer = (function () {
var translationMap = new Map([
["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", "レスポンスコンテンツタイプ"],
["fetching resource", "リソースを取得中"],
["fetching resource list", "リソースリストを取得中"],
["Explore", "探索"],
["Show Swagger Petstore Example Apis", "Swagger Petstore サンプル API を表示"],
["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", "パスから"],
["Click to set as parameter value", "パラメータ値として設定するにはクリック"],
["server returned", "サーバーが返信"]
]);
function translateElement(element) {
$(element).html(translateText($(element).html()));
$(element).val(translateText($(element).val()));
$(element).attr('title', translateText($(element).attr('title')));
}
function translateText(text) {
if (!text) return text;
var trimmedText = text.trim();
return translationMap.has(trimmedText) ? translationMap.get(trimmedText) : text;
}
function localizeUI() {
if ($("#resources_container .resource").length > 0) {
applyTranslation();
}
if ($("#explore").text() === "Explore" && $("#explore").length > 0) {
setTimeout(localizeUI, 50);
}
}
function applyTranslation() {
$('[data-sw-translate]').each(function () {
translateElement(this);
});
}
function setControllerSummaries() {
$.ajax({
type: "GET",
url: $("#input_baseUrl").val(),
dataType: "json",
success: function (data) {
var summaryDict = data.ControllerDesc;
$("#resources_container .resource").each(function () {
var id = $(this).attr("id");
if (id) {
var controllerName = id.substring(9);
var summary = summaryDict[controllerName];
if (summary) {
var option = $(this).children(".heading").children(".options");
if (option.children(".controller-summary").length > 0) {
option.children(".controller-summary").remove();
}
option.prepend('<li class="controller-summary" title="' + summary + '">' + summary + '</li>');
}
}
});
}
});
}
return {
init: function () {
$("#logo").html("会社名").attr("href", "http://www.example.com");
$('body').append('<style>.controller-summary{color:#10a54a !important;word-break:keep-all;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:250px;text-align:right;cursor:default;}</style>');
setControllerSummaries();
localizeUI();
}
};
})();
// ローカライズを実行
SwaggerLocalizer.init();
3. 設定の適用
上記のコードをプロジェクトに追加し、必要な NuGet パッケージ(Swashbuckle)をインストールします。`swagger_localization.js` ファイルは「埋め込みリソース」としてプロジェクトに追加してください。
4. ドキュメントへのアクセス
アプリケーションを実行し、以下の URL にアクセスすることで Swagger UI にアクセスできます。
http://[サイトのアドレス]/swagger