Advanced usage of Web API Helper
ExtApiHelper 不僅能簡化建立回應物件的流程,也能方便地解析請求中的資訊並且進行處理
Table of Contents
Get Request Info
以下示範如何取得從客戶端的請求中各種資訊
示範:
// GET api/values/100?name=Tony
public HttpResponseMessage Get(int id)
{
    ExtApiHelper api = new ExtApiHelper(this);
    string MyHost = api.getMyHost();                      // 客戶端請求時的 host 
    string YourIP = api.getIP();                          // 客戶端的 IP
    string YourUserAgent = api.getUserAgent();            // 客戶端使用的 UserAgent
    string MyCookieValue = api.getCookie("MyCookie");     // 取出 Cookie 中的 MyCookie 數值
    string MyHeaderValue = api.getHeader("MyHeader");     // 取出 Header 中的 MyHeader 數值 
    string QueryName = api.getQuery("name");              // 取出 QueryString 中的 name 數值
    return api.getResponse(new
    {
        MyHost,
        YourIP,
        YourUserAgent,
        MyCookieValue,
        MyHeaderValue,
        QueryName,
        id,
    });
}
輸出:
{
    "MyHost": "http://localhost:61256",
    "YourIP": "::1",
    "YourUserAgent": "PostmanRuntime/7.2.0",
    "MyCookieValue": "123456",
    "MyHeaderValue": null,
    "QueryName": "Tony",
    "id": 100
}
Receive JSON Body
以下示範客戶端以 JSON 方式傳送資料的接收方式
請求:
- URI:POST /api/Values/
- Content-Type:application/json
- Raw Data:
{
    "name": {
        "FirstName" : "Wang",
        "LastName" : "Tony"
    }
}
設計對應的 Model 承接資料
示範:
// 外層 Model
class ModelData 
{
    public ModelName name { get; set; }
}
// 裡層 Model
class ModelName
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}
使用 Model 承接 JSON 格式的資料
示範:
public HttpResponseMessage Post()
{
    ExtApiHelper api = new ExtApiHelper(this);
    // 從 Body 中取出 JSON 資料,並填充到 Model
    ModelData body = api.getJsonBody<ModelData>();
    return api.getResponse(new {
        name = body.name.LastName + body.name.FirstName
    });
}
輸出:
{
    "name": "TonyWang"
}
Uploading File
以下示範客戶端以 multipart/form-data 方式傳送檔案與資料的接收方式
設定 Web.Config
- Storage: 檔案上傳後的儲存位置
- MaxUploadFileSize: 上傳最大檔案大小(byte),預設 5 MB
- maxRequestLength: HTTP 請求最大大小(byte),預設 4 MB
- executionTimeout: HTTP 請求最長等待時間(秒),預設 110 秒
<appSettings>
    <add key="Storage" value="C:\Storage"/>
    <add key="MaxUploadFileSize" value="5242880"/> 
</appSettings>
<system.web>
    <httpRuntime executionTimeout="300" maxRequestLength="5242880"/>
</system.web>
重要 !!:確認專案目錄下有 App_Data 目錄, 該目錄是檔案處理的暫存目錄,如果沒有該目錄請新增它
接下來就可以將檔案上傳至 Storage 目錄下,並取得檔案相關的資訊
請求格式
- URI: /api/upload
- Content-Type: multipart/form-data; boundary=...
- Form: message=123456
- Form: file=....
示範:
[Route("upload")]
public HttpResponseMessage upload()
{
    ExtApiHelper api = new ExtApiHelper(this);
    string name = null;
    long size = 0;
    string type = null;
    string des = null;
    List<ModelFile> files = api.uploadFile(); // 上傳檔案 !!!
    foreach (ModelFile file in files) // 取得檔案訊
    {
        name = file.name; // 新的檔案名稱
        size = file.size; // 檔案大小 (byte)
        type = file.type; // 檔案的 MIME Type
        des = file.des;   // 檔案原始名稱
    }
    ModelData data = api.getFormBody<ModelData>();  // 使用自訂的 Model 取得 Form 中的其他資料
    string message = data.message;              
    return api.getResponse(new
    {
        name,
        size,
        type,
        des,
        message
    });
}
輸出:
{
    "name": "58a7b9c7-a967-4c72-bd23-6172ae5abd0c_123.jpg",
    "size": 32736,
    "type": "image/jpeg",
    "des": "123.jpg",
    "message": "123456"
}
注意事項:
- 新的檔案名稱會自動以 GUID 隨機給予
- 檔案將儲存於 Storage + file.name (新檔案名稱) 位置
SQL Paging Data
當使用 SQL 抓取大量資料時,可能需要批次給予客戶端資料(分頁),分頁輔助函式使用 Identity (primary key) 作為分頁的基準,他將協助你組合出相應的資料存取 SQL 語法,達成這個效果
設定 Web.Config
- APIDataLimit: 每個分頁取得資料筆數
<appSettings>
    <add key="APIDataLimit" value="3"/>
</appSettings>
接下來我們將以這個 SQL 語法作為示範
select cid,cname,since from class where cid>10
以下示範了第一次抓取資料的方式
示範:
ExtApiHelper api = new ExtApiHelper(this);
string sql1 = "select cid,cname,since from class where cid>10";
// api.addIdentityPaging(SQL語句,排序欄位與方式,識別子欄位名稱)
api.addIdentityPaging(ref sql1, "since desc", "cid");
Console.WriteLine(sql1); // 輸出
輸出:
select top(4) cid,cname,since from class where cid>10 order by since desc
| cid | cname | since | 
|---|---|---|
| 100 | Book | 2018-07-20 0:0:0 | 
| 99 | Apple | 2018-07-19 0:0:0 | 
| 98 | Fruit | 2018-07-18 0:0:0 | 
| 97 | Prok | 2018-07-17 0:0:0 | 
此時請注意,預設抓取 n 筆資料(在 Web.config 中設定 APIDataLimit ),但 addIdentityPaging 會抓取 n+1 筆資料,目的是為了判斷是否還能翻下一頁,請自行刪除最後一筆資料並取得最後一筆資料的 ID,作為下一次翻頁的基準
示範:
SQL db = new SQL();
ModelEntity[] data = db.quickQuery<ModelData>(sql);
if(data.Length > int.Parse(Config.get("APIDataLimit")))
{
    // 取出最後一筆的 ID
    string nextId = data[data.Length - 1].cid.ToString(); // 97
    // 刪除最後一筆資料
    Array.Resize(ref data, data.Length - 1); 
}
第二頁(第二次抓取),nextId 為 97:
示範:
ExtApiHelper api = new ExtApiHelper(this);
string sql2 = "select cid,cname,since from class where cid>10";
// api.addIdentityPaging(SQL語句,排序欄位與方式,識別子欄位名稱,最後一筆資料ID)
api.addIdentityPaging(ref sql2, "since desc", "cid", "97");
Console.WriteLine(sql2); // 輸出
輸出:
with tb as(
    select 
        ROW_NUMBER() over(order by since desc) as _seq,
        cid,
        cname,
        since 
    from 
        class 
    where cid>10
) 
select top(4) * from tb where _seq>=(select _seq from tb where cid='97') 
order by since desc
| cid | cname | since | 
|---|---|---|
| 97 | Pork | 2018-07-17 0:0:0 | 
| 96 | Soup | 2018-07-16 0:0:0 | 
| 95 | Tea | 2018-07-15 0:0:0 | 
| 94 | Noodle | 2018-07-14 0:0:0 | 
注意事項
- 欄位名稱 _seq為保留字,請勿使用
- 如果回傳資料筆數大於指定的筆數,表示還有下一頁- 將最後一筆資料的 id 取出,以利下一頁的資料取得
- 請自行移除回傳結果中的最後一筆資料 (可以使用 Array.Resize(ref array, array.Length - 1))
 
- 作者的設計原理