[WebAPI]如何建立WebAPI Client(C#)

  • 5889
  • 0
  • 2014-12-04

摘要:[WebAPI]如何建立WebAPI Client(Console + Web)(C#)

此Client乃是針對前例建立的WebAPI 2

[WebAPI]實作查詢+新增編輯刪除功能WebAPI2(新增Routing機制以及動態LINQ)

 

Web的大概沒人還特地postback回後端才去存取WebAPI吧,應該都用jQuery去做了,而且jQuery做還有Ajax效果

但是c#版本的畢竟還是需要,像是WinForm, WPF, Window Service...這裡就用WinForm的非同步效果做示範

 

先實作Winform的方式呼叫WebAPI

先建立一個Winform專案

 

NuGet安裝WebAPI專用的http Client Library(WebAPI OOXX Http Client OOXX),

它會自動安裝http client library 以及 json.net套件:

 

然後新增一個非同步的function如下, 這是利用之前建立的WebAPI去查詢所有人員的姓名:

用非同步的方式的原因是因為,http client的get, post, put, delete都是非同步的

所以整個function也必須是非同步的,好處就是winform按下其中一個按鈕之後,不會導致

整個畫面鎖住,還是可以繼續按其他的按鈕。

我們首先把處理資料的動作獨立出來一個類別EmployeeDbContext.cs

然後加入下列程式碼來取得所有員工姓名

 string baseAddr = "http://localhost:444/";

        /// 
        /// 取得所有員工資料
        /// 
        /// 
        public async Task GetAllEmpNames()
        {
            string empNames = "";
            using (var client = new HttpClient())
            {
                client.BaseAddress = new Uri(baseAddr);
                client.DefaultRequestHeaders.Accept.Clear();
                client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

                // HTTP GET
                HttpResponseMessage response = await client.GetAsync("api/Employee");
                //response.EnsureSuccessStatusCode();    // Throw if not a success code.
                if (response.IsSuccessStatusCode)
                {
                    var employees = await response.Content.ReadAsAsync>();
                    foreach (var e in employees)
                    {
                         empNames += e.FirstName + " " + e.LastName + "\n";
                     }
                }

                return empNames;
            }
        }/string>

 

然後在畫面上拉幾個簡易的控制項如下:

 

然後設定(查詢)的按鈕的動作,Sum()是故意拖延時間,體驗一下非同步的好處

拖延的那幾秒鐘,仍然可以按下別的按鈕:

private async void btnQuery_Click(object sender, EventArgs e)
        {
            EmployeeDbContext db = new EmployeeDbContext();
            lblQueryStatus.Text = "查詢中...";
            await Task.Run(() => { return Sum(); });//故意delay
            lblQueryResult.Text = await db.GetAllEmpNames();
            lblQueryStatus.Text = "查詢完畢!";

        }
private async Task Sum()
        {
            Stopwatch st = new Stopwatch();            
            int sum1 = 0;
            st.Start();
            for (int i = 0; i < int.MaxValue; i++)
            {
                sum1 += i + 1;
            }
            st.Stop();
            //return "\n故意Delay\n" + (st.ElapsedMilliseconds / 1000).ToString() + "秒";
        }

下面是查詢的結果:

 

然後介紹(新增)Post

為了將來要實作Model.IsValid,也為新增的動作加入一個類別EmployeeInsert

 class EmployeeInsert
    {       
        public string LastName { get; set; }
        public string FirstName { get; set; }
        public string Title { get; set; }
        public Nullable BirthDate { get; set; }
        public string Address { get; set; }
        public string City { get; set; }
        public string EmpType { get; set; }
    }

 

然後利用以下程式碼存取WebAPI, 以進行資料新增

public async Task InsertNewEmp(EmployeeInsert newEmp)
        {
            Boolean insertSuccess = false;//是否新增資料成功
            using (var client = new HttpClient())
            {
                client.BaseAddress = new Uri(baseAddr);
                client.DefaultRequestHeaders.Accept.Clear();
                client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

                // HTTP GET
                HttpResponseMessage response = await client.PostAsJsonAsync("api/Employee/Insert", newEmp);
                if (response.IsSuccessStatusCode)
                {
                    //根據http 1.1, 回傳的header.location會有剛剛送出的網址
                    //即http://localhost:444/api/Employee/Insert
                    //既然回傳了就順便取出來
                    Uri newEmpUri = response.Headers.Location;
                    insertSuccess = true;
                }
            }
            return insertSuccess;
        }

最後定義按下insert按鈕的事件:

private async void btnInsert_Click(object sender, EventArgs e)
        {            
            //新增都是以建立Employee物件的方式進行,因為這樣才能順便一起把Model.isValid做好
            EmployeeDbContext db = new EmployeeDbContext();
            Boolean insertSuccess = false;//是否新增成功
            EmployeeInsert emp = new EmployeeInsert();
            string nowString = DateTime.Now.ToString("MMddhhmmss");
            emp.FirstName = "Yen" + nowString;
            emp.LastName = "ChiaChi" + nowString;
            emp.City = "New Taipei City" + nowString;

            try
            {
                insertSuccess = await db.InsertNewEmp(emp);
                if(insertSuccess == true)
                {
                    lblInsertResult.Text = "新增成功!";                               
                }
                else
                {
                    lblInsertResult.Text = "新增失敗!";                               
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }

按下新增按鈕後,畫面顯示新增成功:

 

接下來示範更新update:

新增一個EmployeeUpdate類別,以供未來做Model驗證之用

 class EmployeeUpdate
    {
        public string LastName { get; set; }
        public string FirstName { get; set; }     
        public string City { get; set; }

    }

然後在EmployeeDbContext.cs加入程式碼,利用Put method去更新資料

 public async Task UpdateEmp(int EmployeeID ,EmployeeUpdate updateEmp)
        {
            Boolean updateSuccess = false;//是否更新資料成功
            using (var client = new HttpClient())
            {
                client.BaseAddress = new Uri(baseAddr);
                //client.BaseAddress = new Uri("http://localhost:2394/");
            
                client.DefaultRequestHeaders.Accept.Clear();
                client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

                // HTTP Put
                HttpResponseMessage response = await client.PutAsJsonAsync("api/Employee/Update/" + EmployeeID, updateEmp);
                if (response.IsSuccessStatusCode)
                {                  
                    updateSuccess = true;
                }
            }
            return updateSuccess;
        }

 

按下編輯按鈕的時候,會去執行update員工資料,一樣是用非同步的方式去寫

private async void btnEdit_Click(object sender, EventArgs e)
        {
            //新增都是以建立Employee物件的方式進行,因為這樣才能順便一起把Model.isValid做好
            lblEditStatus.Text = "修改中...";
            EmployeeDbContext db = new EmployeeDbContext();
            Boolean updateSuccess = false;//是否update成功
            EmployeeUpdate updateEmp = new EmployeeUpdate();
            string nowString = DateTime.Now.ToString("MMddhhmmss");
            updateEmp.FirstName = "FirstNameChangedTo" + nowString;
            updateEmp.LastName = "LastNameChangedTo" + nowString;
            updateEmp.City = "CityChangedTo" + nowString;
            //await Task.Run(() => { return Sum(); });//故意delay
            try
            {
                updateSuccess = await db.UpdateEmp(15, updateEmp);
                if (updateSuccess == true)
                {
                    lblEditResult.Text = "修改成功!";
                }
                else
                {
                    lblEditResult.Text = "修改失敗!";
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }

        }

最後按下修改按鈕,顯示修改成功

 

然後示範刪除:

首先於EmployeeDbContext.cs加入程式碼,利用WebAPI去刪除資料

public async Task DeleteEmp(int EmployeeID)
        {
            Boolean delSuccess = false;//是否刪除資料成功
            using (var client = new HttpClient())
            {
                client.BaseAddress = new Uri(baseAddr);
               
                client.DefaultRequestHeaders.Accept.Clear();
                client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

                // HTTP delete
                HttpResponseMessage response = await client.DeleteAsync("api/Employee/Delete/" + EmployeeID);
                if (response.IsSuccessStatusCode)
                {
                    delSuccess = true;
                }
            }
            return delSuccess;
        }

然後在刪除的按鈕加入上述刪除的動作

 private async void btnDel_Click(object sender, EventArgs e)
        {
            lblDelStatus.Text = "刪除中...";
            EmployeeDbContext db = new EmployeeDbContext();
            Boolean delSuccess = false;//是否刪除成功
            delSuccess =await db.DeleteEmp(40);
            if (delSuccess == true)
            {
                lblDelResult.Text = "刪除成功!";
                
            }
            else
            {
                lblDelResult.Text = "刪除失敗!";
            }
        }

然後執行之後,按下刪除按鈕,顯示刪除成功

 

這樣子C#版本的Client去使用WebAPI就算完成囉

下一篇要寫jQuery版本的

 

PS.突然想起來一個重點,要怎麼用C#去做Authentication去呼叫https的WebAPI?

研究一下,如果研究出來再來這邊補充

參考資料:

Calling a Web API From a .NET Client (C#)

[C#].NET 4.5 async 與 await 簡化非同步開發

[Web API] WinForm 使用 HttpClient 呼叫 Web API