Asp.Net Core Swagger Required 設定

Asp.Net Core 中,安裝 Swagger 非常方便,但我一直無法設定必要欄位,

目前只好自己寫一個 OperationFilter 來達到想要的功能。

首先安裝 Swagger,請參考這裡,安裝非常容易。

接下來讓我們自己產生 OperationFilter,參考以下程式碼

public class RequiredAttributeOperationFilter : IOperationFilter {

	/// <summary>
	/// 
	/// </summary>
	/// <param name="operation"></param>
	/// <param name="context"></param>
	public void Apply(Operation operation, OperationFilterContext context) {
		//沒有參數
		if (operation.Parameters == null) return;

		for (int i = 0; i < operation.Parameters.Count; i++) {
			var op_param = operation.Parameters[i];
			//參數是 FromBody,就不處裡了
			if (op_param.In.Equals("body")) continue;

			//根據名稱找出 API 參數
			var api_param = context.ApiDescription.ActionDescriptor.Parameters.FirstOrDefault(f => f.Name.Equals(op_param.Name)) as ControllerParameterDescriptor;
			if (api_param != null) {
				//檢查參數屬性有沒有 RequiredAttribute 
				if (api_param.ParameterInfo.CustomAttributes.Any(data => data.AttributeType == typeof(RequiredAttribute))) {
					op_param.Required = true;
				}
				continue;
			}

			//根據名稱找出物件欄位
			var field_param = context.ApiDescription.ParameterDescriptions.FirstOrDefault(f => f.Name.Equals(op_param.Name));
			if (field_param != null) {
				//檢查物件欄位有沒有 RequiredAttribute
				var attrs = ((DefaultModelMetadata)field_param.ModelMetadata).Attributes.PropertyAttributes;
				if (attrs != null && attrs.Any(attr => attr.GetType() == typeof(RequiredAttribute))) {
					op_param.Required = true;
				}
				continue;
			}
		}
	}
}

這裡有兩個參數 Operation 和 OperationFilterContext,

Operation 是紀錄 Web Api 的所有參數的顯示方式,是 Swagger 描述端點文檔的一部分。

OperationFilterContext 是 method 相關的資訊,這裡有兩個需要特別說明的地方,

讓我們舉個例子

public class UserProfile {
	public string Name { get; set; }
	public int Age { get; set; }
}

[HttpGet]
public string GetSomething(string id, UserProfile profile) {
	...
}

如果 GetSomething 的參數有兩個,string 和 UserProfile,

那麼 OperationFilterContext.ApiDescription.ActionDescriptor.Parameters 就會有兩個 ParameterDescriptor 元素,

一個是 id, 另一個是 profile

而 OperationFilterContext.ApiDescription.ParameterDescriptions 會有三個 ApiParameterDescription 元素,

分別是 id、Name、Age。

若是在 GetSomething 的參數裡設定屬性,則只能在 ParameterDescriptor 找到,

而類別裡的欄位設定的屬性只能從 ApiParameterDescription 取得,

所以 RequiredAttributeOperationFilter 裡會先從參數找起,在去找欄位。

因此我們就可以設定成

public class UserProfile {
	[Required]
	public string Name { get; set; }
	public int Age { get; set; }
}

[HttpGet]
public string GetSomething([Required]string id, UserProfile profile) {
	...
}

這樣在 Swagger UI顯示 id 和 Name 參數時都會加上 (required) 說明,如下圖箭頭處