iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 7
1
Modern Web

ASP.NET Web Form 入門30天系列 第 7

[ASP.NET] 使用開放資料( Open Data ) 實作篇,以"高雄市政府相關求才資訊發佈"為例 (三) - 程式碼解析(B篇)

  • 分享至 

  • xImage
  •  

本篇擷取重點:

  1. 繼續解析本篇副程式程式碼的部分
  2. 相對主程式,副程式的概念及應用方式
  3. 網頁傳遞參數的方法(GET/POST)及應用

我們在 上一篇 透析了主程式部分的程式碼,

這篇,我們將接著繼續進行 副程式(GetJsonContent)部分 的程式碼解析。

但在開始之前,我們要先來聊聊 什麼是副程式?


一、什麼是副程式?

  1. 副程式的主要用途, 是把一些會常用/多次重複使用的程式碼獨立寫作一個副程式。當程式的某一部分需要用到這些程式碼時, 就可以直接呼叫副程式來使用。

==================================================================
貼心小補充:

本篇雖將 函式/方法 稱為 副程式 方便瀏覽者想像,但其實物件導向中沒有所謂的 "副程式" (routine) 的說法,可能要早點習慣用 "函式" (function) 或 "方法" (method) 的詞彙,因為有些 "副程式" 可以寫得跟 "主程式" 一樣 :),當然這是要適當規劃才會有這種情況,若是在同一個副程式中處理所有的事是不算的喔...

==================================================================


  1. 主程式呼叫副程式的語法
副程式名稱(參數1,參數2)

以本題為例,GetJsonContent為副程式名稱,丟進去的參數為那一串網址字串:

string content = GetJsonContent("https://www.ktec.gov.tw/ktec_api.php?type=json");

  1. 副程式的基本語法
static void 副程式名稱(資料型態1 參數1,資料型態2 參數2)
{
   程式區塊
}

// Note:這邊的參數可以是變數或陣列

以本題為例,因為丟入副程式的參數是一串網址字串,故須在副程式裡面建立一個 字串變數Url 來接。

private static string GetJsonContent(string Url)
{
    程式區塊
}

  1. 方法的常見宣告:
  • static 靜態宣告,靜態方法在程式加載時就已經存在,故在使用前無需初始化(new)就能直接訪問。

  • void 沒有返回值宣告,也就是沒有return 關鍵字。

  • public / private / protected 皆是為了控制類別外部的存取權而設定的東西。

    • 設成private時,外部的類別就無法存取,
    • 設成public時,外部的任何類別都可以存取,
    • 設成protected時,只有自身類別(父類別)和衍生類別(繼承該類別的子類別)才能夠存取。

參考資料:
http://mermerism.blogspot.com/2014/04/blog-post_3.html -(更多 副程式 )
http://weisnote.blogspot.com/2012/08/static.html -(更多 static宣告 )


二、副程式(GetJsonContent)程式碼之解析

接下來進入副程式(GetJsonContent)之程式碼解析的部分

private static string GetJsonContent(string Url)
{
    string targetURI = Url;
    var request = System.Net.WebRequest.Create(targetURI); 
    request.ContentType = "application/json; charset=utf-8";
    var response = request.GetResponse();
    string text;
    using (var sr = new StreamReader(response.GetResponseStream()))
    {
        text = sr.ReadToEnd();
    }
    return text;
}

因為在主程式引用GetJsonContent方法(副程式)時,丟入的參數是一串網址字串,故須在副程式裡面建立一個 字串變數Url 來接。(這裡設的變數名稱僅在此方法內使用,雖然怎麼命名並不會影響外面引用,但實務上還是會盡量讓變數名稱和方法內的參數相同,比較容易辨別,這是比較好的寫作習慣~)

感謝 YoChen 網友的觀念提供!


string targetURI = Url;
var request = System.Net.WebRequest.Create(targetURI); 

設字串targetURL來接丟進副程式字串參數string Url。
設變數request來向targetURI網址送出請求,怎麼請求?
使用【System.Net命名空間】中的【WebRequest類別】的【create方法】來向【targetURI】請求


request.ContentType = "application/json; charset=utf-8"; 

告訴伺服器端,即將傳輸的請求資料的MIME類型


var response = request.GetResponse(); 

設變數response來接送出請求之伺服器之response。


string text; 
using (var sr = new StreamReader(response.GetResponseStream()))
{
    text = sr.ReadToEnd();
}

建立一個字串text,方便後面使用

利用response.GetResponseStream()方法,回傳來自網際網路資源的資料流(stream),並透過初始化StreamReader類別來從資料流中(Stream)讀取字元,最後再建立一個物件sr來接。

using 陳述式:在建立物件sr的當時,使用 using 陳述式,當這個區塊程式碼結束執行之後,能確保該物件所佔用的資源一定會被完整釋放。

ReadToEnd()方法是直接讀取資料流中,目前位置開始到整個資料流結束的所有字元,並且回傳string 型別結果字串,代入前面建立的字串text。


return text;

除非副程式有宣告void,不然該副程式必有回傳值。

以本題GetJsonContent副程式為例,副程式並未宣告void,故必定要有回傳值,

丟進去的參數:"https://www.ktec.gov.tw/ktec_api.php?type=json" (string Url)。

回傳值為:字串text

參考資料:
https://blog.miniasp.com/post/2009/10/12/About-CSharp-using-Statement-misunderstanding-on-try-catch-finally -(更多 Using 陳述句 )
http://www.kangting.tw/2019/06/stream_24.html -(更多 Stream-字元資料讀寫 )


今天的分享到這邊告一段落,

由於筆者也仍處在學習階段,如果有不正確的地方,也煩請指教,感謝各位大大!!


上一篇
[ASP.NET] 使用開放資料( Open Data ) 實作篇,以"高雄市政府相關求才資訊發佈"為例 (二) - 程式碼解析(A篇)
下一篇
[ASP.NET] https://網址?參數=參數值 ,URL 網址參數解析,取得網址參數
系列文
ASP.NET Web Form 入門30天30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

2 則留言

1
YoChen
iT邦研究生 1 級 ‧ 2019-09-09 11:53:04

void 沒有返回值宣告,也就是沒有renturn 關鍵字。
使用【System.Net命名空間】中的【WebRequest類別】的【reate方法】來向【targetURI】請求

Return跟Create有錯字哦~XDDD

設成protected時,只有在同一個package或繼承該類別後才能夠存取

應該是只有繼承的子類別才能存取

因為在主程式引用GetJsonContent方法(副程式)時,丟入的參數是一串網址字串,故須在副程式裡面建立一個 字串變數Url 來接。(這裡設的變數名稱僅在此方法內使用,所以怎麼命名其實沒這麼重要,並不會影響外面引用)

實務上還是會盡量讓變數名稱方法內的參數相同,比較容易辨別,這是比較好的寫作習慣~

string text; 
using (var sr = new StreamReader(response.GetResponseStream()))
{
    text = sr.ReadToEnd();
}
return text;

這一段可以簡化成

using (var sr = new StreamReader(response.GetResponseStream()))
{
    return sr.ReadToEnd(); 
}

即使return過後,sr.Dispose()還是會被執行~

謝謝大大的錯誤更正及觀念提供,不過還想請問一下,當我們將該成員宣告成protected保護層級,不是可供自身類別(父類別)和衍生類別(子類別)存取該成員嗎?

YoChen iT邦研究生 1 級 ‧ 2019-09-10 09:58:08 檢舉

protected可供自身類別(父類別)和衍生類別(子類別)存取該成員

沒錯哦~您說的是對的,是我表達得不夠完整~XDDD

設成protected時,只有在同一個package或繼承該類別後才能夠存取

但通常我們說的同一個Package,通常是說在同一個Namespace,畢竟他們最後都會被包在同一份dll中,如果以這樣的觀點出發,您在文中的描述就會有點問題~XDDD

了解,謝謝大大的詳細解釋!!

我也一直對這個Package的定義是什麼感到疑惑,所以才選擇直接貼上原文的說法XDD,馬上修改哈哈哈哈

1
小朱
iT邦新手 4 級 ‧ 2019-09-13 17:54:05
  1. 物件導向中沒有所謂的 "副程式" (routine) 的說法,可能要早點習慣用 "函式" (function) 或 "方法" (method) 的詞彙喔,因為有些 "副程式" 可以寫得跟 "主程式" 一樣 :),當然這是要適當規劃才會有這種情況,若是在同一個副程式中處理所有的事是不算的喔...
  2. C# 還有一種範圍修飾詞 internal,用在限定同一組件內的程式才可以存取,但這是 C# 語言的議題,不在這多做討論。
  3. WebRequest 的作法可考慮換成 WebClient 會更簡單,只要用 DownloadString() 就可以了。

收到,感謝幫助確立觀念,但若直接把文章內的副程式改成函式/方法,文章變得有點生硬難閱讀,所以我將大大整理的觀念放在文章最前頭的補充部分!

我要留言

立即登入留言