一直以來在使用或測試開發的WebAPI,都是透過html Client的jQuery Ajax或者Google Chrome的工具【Dev HTTP Client】。不過最近小喵有個需求要在ASP.NET的系統中,在Server來存取Web API,於是著手來尋找相關的寫法,發現網路上這類範例還蠻分散的。小喵就整理一下,透過 HttpClient 存取 WebAPI ,並且可以傳送指定的 Head 。以下來看看相關範例~
緣起
一直以來在使用或測試開發的WebAPI,都是透過html Client的jQuery Ajax或者Google Chrome的工具【Dev HTTP Client】。不過最近小喵有個需求要在ASP.NET的系統中,在Server來存取Web API,於是著手來尋找相關的寫法,發現網路上這類範例還蠻分散的。小喵就整理一下,透過 HttpClient 存取 WebAPI ,並且可以傳送指定的 Head 。以下來看看相關範例~
GET
先從最基本的Get方法來測試起
這邊的範例有兩種,一個是透過 HttpClient 的【GetAsync】,另一個是搭配【HttpRequestMessage】+【SendAsync】的方式,以下就分別來看這兩種方式
GET方式一:GetAsync
首先是最基本的 GetAsync,在使用前我們畫面先準備一個輸入WebAPI 的Textbox,以及一個按鈕,希望按下按鈕後,根據TextBox輸入的WebAPI來取得資料,希望傳回JSON的相關內容,把傳回的內容放在一個TextBox TextMode=MultiLine
畫面安排:
URI:<asp:TextBox ID="txtURI" runat="server" Width="631px" Text="http://localhost:1823/api/products"></asp:TextBox>
<br />
Get:<br />
<asp:Button ID="btnGet1" runat="server" Text="簡單的Get" /><br />
<hr />
<asp:TextBox ID="txtRlt" runat="server" TextMode="MultiLine" Height="162px" Width="741px"></asp:TextBox>
接著就來撰寫這個按鈕按下的動作,相關程式碼如下:
'宣告HttpClient
Dim client As New HttpClient()
'宣告ResponseMessage來承接回傳的內容
Dim rspn As HttpResponseMessage
'WebAPI的Uri
Dim uriWebApi As New Uri(Me.txtURI.Text)
'透過GetAsync非同步呼叫WebAPI,結果傳給ResponseMessage
rspn = Await client.GetAsync(uriWebApi)
'確認成功
rspn.EnsureSuccessStatusCode()
'讀取回傳的內容
Dim Content As String = Await rspn.Content.ReadAsStringAsync()
'顯示回傳的內容
Me.txtRlt.Text = Content
問題排除
不過這時候會發現,部分程式碼下方會出現一些小蝌蚪,原因是因為我們使用非同步的方式,那麼相對的Onclick的Sub也要對應為非同步,這部分可以由Visual Studio來幫我們修正
修正後,會發現我們的Button Click的Sub多了Async的設定
Protected Async Sub btnGet1_Click(sender As Object, e As EventArgs) Handles btnGet1.Click
接著運行看看,又會出現如下的錯誤訊息:
這部分一樣是因為使用了非同步,所以在aspx的page設定中,需加上【Async="true"】,這樣就可以正常的讀取WebAPI囉
PS.如果WebAPI讀取有問題,那麼需要針對WebAPI設定為可以跨網預存取,這個部分請參考以下 MVP KKBruce 的這篇
GET方式二:HttpRequestMessage + SendAsync 傳遞自訂 Head
在WebAPI使用過程中,我們可能還會透過Header來傳送一些資訊,因此我們再來測試看看,HttpClient 的 SendAsync 搭配 HttpRequestMessage來做GET
這裡我們先在畫面上安排輸入多筆Head的部分
首先我們先定義myHead物件,然後透過物件集合的搭配ViewState將輸入的內容放在GridView裡面
myHead類別:
<Serializable> _
Public Class myHead
Public Property HeadName As String = ""
Public Property HeadValue As String = ""
End Class
在我們的Code File中宣告Heads物件集合
'定義Head物件集合
Dim Heads As List(Of myHead)
在PageLoad事件中準備物件集合
Protected Sub Page_Load(sender As Object, e As EventArgs) Handles Me.Load
'從ViewState取得Heads物件集合
Heads = ViewState("Heads")
If Heads Is Nothing Then
'如果是空的(ViewState是空的),New一個物件集合
Heads = New List(Of myHead)
'將物件集合存入ViewState
ViewState("Heads") = Heads
End If
End Sub
畫面中安排維護Heads的相關控制項:
Heads:
<table>
<thead>
<tr>
<td>
<asp:TextBox ID="txtHeadName" runat="server"></asp:TextBox>
</td>
<td>:</td>
<td>
<asp:TextBox ID="txtHeadValue" runat="server"></asp:TextBox>
</td>
<td>
<asp:Button ID="btnAddHead" runat="server" Text="加入Head" />
</td>
</tr>
</thead>
</table>
<asp:GridView ID="gvHeads" runat="server" AutoGenerateColumns="False">
<Columns>
<asp:CommandField ShowDeleteButton="True" />
<asp:BoundField DataField="HeadName" HeaderText="HeadName" SortExpression="HeadName" />
<asp:BoundField DataField="HeadValue" HeaderText="HeadValue" SortExpression="HeadValue" />
</Columns>
</asp:GridView>
編輯Heads的部分,這裡不是重點,就直接表過不詳提
Private Sub gvHeadReBind()
ViewState("Heads") = Heads
Me.gvHeads.DataSource = Heads
Me.gvHeads.DataBind()
End Sub
Protected Sub btnAddHead_Click(sender As Object, e As EventArgs) Handles btnAddHead.Click
Dim tHead As New myHead
tHead.HeadName = Me.txtHeadName.Text
tHead.HeadValue = Me.txtHeadValue.Text
Heads.Add(tHead)
gvHeadReBind()
End Sub
Protected Sub gvHeads_RowDeleting(sender As Object, e As GridViewDeleteEventArgs) Handles gvHeads.RowDeleting
Dim idx As Integer = e.RowIndex
Heads.RemoveAt(idx)
gvHeadReBind()
End Sub
再來才是重點,透過 HttpClient 的 Hy 搭配 HttpRequestMessage 來處理 GET
'宣告HttpClient
Dim client As New HttpClient()
'宣告ResponseMessage來承接回傳的內容
Dim rspn As HttpResponseMessage
'WebAPI的Uri
Dim uriWebApi As New Uri(Me.txtURI.Text)
'定義RequestMessage
Dim rq As New HttpRequestMessage()
'設定Request的Uri
rq.RequestUri = uriWebApi
'逐一讀取Head
For Each tHead As myHead In Heads
rq.Headers.Add(tHead.HeadName, tHead.HeadValue)
Next
'透過SendAsync非同步呼叫WebAPI,結果傳給ResponseMessage
rspn = Await client.SendAsync(rq)
'確認成功
rspn.EnsureSuccessStatusCode()
'讀取回傳的內容
Dim Content As String = Await rspn.Content.ReadAsStringAsync()
'顯示回傳的內容
Me.txtRlt.Text = Content
這樣就可以搭配自訂的 Head 來GET(讀取) WebAPI
POST
接下來測試POST的部分。POST的部分需要一個Body放置要送出的內容。
Body:<br />
<asp:TextBox ID="txtBody" runat="server" TextMode="MultiLine" Height="134px" Width="735px"></asp:TextBox>
PS.在REST的基本來看POST主要是用來做Insert,不過其實POST也不一定就只做Insert,我們還是可以透過POST來做複雜條件的GET或者複雜條件、多筆的Update,不過關於這部分屬於WebAPI怎麼寫的範圍,這邊就表過不提。
一樣的POST可以有兩種方式,一個是透過【HttpClient的PostAsync】,另一個是使用【SendAsync】,以下來分別列出相關範例:
POST : PostAsync
'宣告HttpClient
Dim client As New HttpClient()
'宣告要送出的Body內容
Dim hContent As HttpContent = New StringContent(Me.txtBody.Text)
'設定Body內容的格式
hContent.Headers.ContentType = New MediaTypeHeaderValue("application/json")
'WebAPI的Uri
Dim uriWebAPI As New Uri(Me.txtURI.Text)
'宣告ResponseMessage來承接回傳的內容
Dim rspn As HttpResponseMessage = Await client.PostAsync(uriWebAPI, hContent)
'讀取回傳的內容,並顯示在txtRlt中
Me.txtRlt.Text = Await rspn.Content.ReadAsStringAsync
POST : SendAsync + Heads
'宣告HttpClient
Dim client As New HttpClient()
'宣告ResponseMessage來承接回傳的內容
Dim rspn As HttpResponseMessage
'WebAPI的Uri
Dim uriWebApi As New Uri(Me.txtURI.Text)
'定義RequestMessage
Dim rq As New HttpRequestMessage()
'設定Request的Uri
rq.RequestUri = uriWebApi
'逐一設定Header內容
For Each tHead As myHead In Heads
rq.Headers.Add(tHead.HeadName, tHead.HeadValue)
Next
'設定Request的Method為Post
rq.Method = HttpMethod.Post
'宣告要送出的Body內容
Dim hContent As HttpContent = New StringContent(Me.txtBody.Text)
'設定Body內容的格式
hContent.Headers.ContentType = New MediaTypeHeaderValue("application/json")
'設定RequestMessage的Content是hContent
rq.Content = hContent
'宣告ResponseMessage來承接回傳的內容
rspn = Await client.SendAsync(rq)
'確認成功
rspn.EnsureSuccessStatusCode()
'讀取回傳的內容
Dim rtnContent As String = Await rspn.Content.ReadAsStringAsync()
'顯示回傳的內容
Me.txtRlt.Text = rtnContent
PUT
PUT的部分,一樣會有個Body來放要更新的內容,這部分就直接套用POST那部分所用道的txtBody這個控制項即可
PUT一樣這邊示範兩種方式:分別是HttpClient的【PutAsync】、【SendAsync】
PUT : PutAsync
Protected Async Sub btnPut1_Click(sender As Object, e As EventArgs) Handles btnPut1.Click
'宣告HttpClient
Dim client As New HttpClient()
'宣告要送出的Body內容
Dim hContent As HttpContent = New StringContent(Me.txtBody.Text)
'設定Body內容的格式
hContent.Headers.ContentType = New MediaTypeHeaderValue("application/json")
'WebAPI的Uri
Dim uriWebAPI As New Uri(Me.txtURI.Text)
'宣告ResponseMessage來承接回傳的內容
Dim rspn As HttpResponseMessage = Await client.PutAsync(uriWebAPI, hContent)
'讀取回傳的內容,並顯示在txtRlt中
Me.txtRlt.Text = Await rspn.Content.ReadAsStringAsync
End Sub
PUT : SendAsync + Heads
Protected Async Sub btnPutHead_Click(sender As Object, e As EventArgs) Handles btnPutHead.Click
'宣告HttpClient
Dim client As New HttpClient()
'宣告ResponseMessage來承接回傳的內容
Dim rspn As HttpResponseMessage
'WebAPI的Uri
Dim uriWebApi As New Uri(Me.txtURI.Text)
'定義RequestMessage
Dim rq As New HttpRequestMessage()
'設定Request的Uri
rq.RequestUri = uriWebApi
'逐一設定Header內容
For Each tHead As myHead In Heads
rq.Headers.Add(tHead.HeadName, tHead.HeadValue)
Next
'設定Request的Method為Put
rq.Method = HttpMethod.Put
'宣告要送出的Body內容
Dim hContent As HttpContent = New StringContent(Me.txtBody.Text)
'設定Body內容的格式
hContent.Headers.ContentType = New MediaTypeHeaderValue("application/json")
'設定RequestMessage的Content是hContent
rq.Content = hContent
'宣告ResponseMessage來承接回傳的內容
rspn = Await client.SendAsync(rq)
'確認成功
rspn.EnsureSuccessStatusCode()
'讀取回傳的內容
Dim rtnContent As String = Await rspn.Content.ReadAsStringAsync()
'顯示回傳的內容
Me.txtRlt.Text = rtnContent
End Sub
DELETE
最後是Delete
Delete的部分就指示範簡單的刪除,如果要透過SendAsync來刪除,大概與上面的差不多。
Delete : DeleteAsync
Protected Async Sub btnDel1_Click(sender As Object, e As EventArgs) Handles btnDel1.Click
'宣告HttpClient
Dim client As New HttpClient()
'宣告ResponseMessage來承接回傳的內容
Dim rspn As HttpResponseMessage
'WebAPI的Uri
Dim uriWebApi As New Uri(Me.txtURI.Text)
'透過GetAsync非同步呼叫WebAPI,結果傳給ResponseMessage
rspn = Await client.DeleteAsync(uriWebApi)
'確認成功
rspn.EnsureSuccessStatusCode()
'讀取回傳的內容
Dim Content As String = Await rspn.Content.ReadAsStringAsync()
'顯示回傳的內容
Me.txtRlt.Text = Content
End Sub
以下是簽名:
- 歡迎轉貼本站的文章,不過請在貼文主旨上加上【轉貼】,並在文章中附上本篇的超連結與站名【topcat姍舞之間的極度凝聚】,感恩大家的配合。
- 小喵大部分的文章會以小喵熟悉的語言VB.NET撰寫,如果您需要C#的Code,也許您可以試著用線上的工具進行轉換,這裡提供幾個參考
Microsoft MVP Visual Studio and Development Technologies (2005~2019/6) | topcat Blog:http://www.dotblogs.com.tw/topcat |