定義API回傳物件

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);
        }

元哥的筆記