WEB API
最近在寫專案稍微記錄一下定義泛型的API的物件,下次懶得再回想,直接呼叫調用,順便有跟同事講這一塊自己是怎麼使用列舉說明和定義API的物件
以.Net Core Web Api為例,建立新專案,這些步驟直接略過了,定義以下要回傳的狀態以及列舉說明擴充方法
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Threading.Tasks;
namespace WebApplication1.ViewModel
{
public enum ResponseCode
{
// ==========================================
// 1. 通用與成功狀態 (200 ~ 299)
// ==========================================
/// <summary>
/// 成功
/// </summary>
[Description("成功")]
Success = 200,
// ==========================================
// 2. 客戶端與請求錯誤 (400 ~ 499)
// ==========================================
[Description("異常錯誤")]
BadRequest = 400,
/// <summary>
/// 登入驗證
/// </summary>
[Description("尚未登入或憑證無效")]
Unauthorized = 401,
/// <summary>
/// 資料操作權限
/// </summary>
[Description("拒絕存取,您沒有此操作權限")]
Forbidden = 403,
/// <summary>
/// 查資料,沒有資料
/// </summary>
[Description("查無此資料")]
NotFound = 404,
/// <summary>
/// 重複資料
/// </summary>
[Description("資料發生衝突或重複提交")]
Conflict = 409,
/// <summary>
/// 連續寫入好幾次的時候,統計次數
/// </summary>
[Description("請求過於頻繁,請稍後再試")]
TooManyRequests = 429,
// ==========================================
// 3. 資料與邏輯處理異常 (600 ~ 699 自訂區段)
// ==========================================
/// <summary>
/// 驗證資料欄位
/// </summary>
[Description("欄位資料驗證失敗")]
ValidationError = 600,
/// <summary>
/// 通常用途在業務邏輯判斷條件的時候回傳失敗訊息
/// </summary>
[Description("資料狀態不正確,無法執行此操作")]
InvalidState = 605,
// ==========================================
// 4. 伺服器與系統層級錯誤 (500 ~ 599)
// ==========================================
/// <summary>
/// 系統異常錯誤
/// </summary>
[Description("系統發生非預期錯誤")]
SystemError = 500,
/// <summary>
/// 外部用途
/// </summary>
[Description("外部服務或 API 呼叫異常")]
BadGateway = 502,
}
}
public class ResponseResult<T>
{
/// <summary>
/// 執行成功與否
/// </summary>
public bool IsSuccess { get; set; }
/// <summary>
/// 狀態碼
/// </summary>
public ResponseCode ResponseCode { get; set; }
/// <summary>
/// 錯誤訊息
/// </summary>
public string Message { get; set; } = string.Empty;
/// <summary>
/// 資料本體
/// </summary>
public T? Data { get; set; }
// 欄位錯誤
public List<ValidationError> ValidationErrors { get; set; } = new List<ValidationError>();
/// <summary>
/// 成功
/// </summary>
/// <returns></returns>
public ResponseResult<T> Success()
{
ResponseCode = ResponseCode.Success;
IsSuccess = true;
Message = ResponseCode.Success.GetEnumDescription();
return this;
}
/// <summary>
/// 成功回傳資料
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
public ResponseResult<T> Success(T data)
{
ResponseCode = ResponseCode.Success;
IsSuccess = true;
Data = data;
Message = ResponseCode.Success.GetEnumDescription();
return this;
}
/// <summary>
/// 失敗
/// </summary>
/// <param name="responseCode">代碼</param>
/// <param name="validationErrors">欄位驗證錯誤</param>
/// <param name="customMessage">遇到業務邏輯或是其他問題時的自訂訊息未塞怎抓預設</param>
/// <returns></returns>
public ResponseResult<T> Fail(
ResponseCode responseCode,
List<ValidationError>? validationErrors = null,
string? customMessage = null)
{
IsSuccess = false;
ResponseCode = responseCode;
Message = customMessage ?? responseCode.GetEnumDescription();
ValidationErrors = validationErrors ?? new List<ValidationError>();
return this;
}
}
public class ValidationError
{
public string Field { get; set; } = string.Empty;
public string ErrorMessage { get; set; } = string.Empty;
}
}
上述定義了列舉狀態之後,再回頭定義擴充方法,定義取說明
namespace WebApplication1
{
public static class MyExtensions
{
public static string GetEnumDescription(this Enum value)
{
FieldInfo fi = value.GetType().GetField(value.ToString());
DescriptionAttribute[] attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
//若取不到屬性,則取名稱
if ((attributes != null) && (attributes.Length > 0))
return attributes[0].Description;
else
return value.ToString();
}
}
}定義一個回傳的Customer資料物件
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace WebApplication1.ViewModel
{
public class ReponseCustomerVM
{
public string CustomerId { get; set; }
public string CustomerName { get; set; }
}
}
API端部分塞假資料,若是回傳成功把撈取資料的塞在Success物件裡面。
[HttpGet]
[Route("Customer/All")]
public ResponseVM<List<ReponseCustomerVM>> GetCustomers()
{
var responseCustomers = new List<ReponseCustomerVM>();
responseCustomers.Add(new ReponseCustomerVM
{
CustomerId = "001",
CustomerName = "AA"
});
responseCustomers.Add(new ReponseCustomerVM
{
CustomerId = "002",
CustomerName = "BB"
});
return new ResponseVM<List<ReponseCustomerVM>>()
.Success(responseCustomers);
}
元哥的筆記