包含標籤 Bug 的文章

菜雞抓蟲: DateTime.ToString() 之我們不一樣 & CultureInfo 文化特性小筆記

Image

事發緣由

咱們內部套件中有個方法,會將各個參數組合為 QueryString 去打指定的 Api。就是這麼稀鬆平常的場景,神奇的事情就發生了。

同樣的套件、同樣的語法,在團隊中兩個人的電腦上安裝執行,卻是一個成功一個失敗。

原來該方法的參數中,包含一欄型別為 DateTime 的資料,並且會把該欄位的值拿來 ToString() 再做為參數傳遞給目標 Api。

而呼叫失敗的人就是在這個 DateTime.ToString() 的過程中產生了中文字,使得目標 Api 接到參數後,無法將中文字轉換回 DateTime 而發生了錯誤。

問題就浮現了:同一行 DateTime.ToString() 在不同電腦執行的結果竟然不一樣?!

為了讓我們更快了解狀況,現在就簡單地使用 Linqpad 進行測試:

void Main()
{
    DateTime.Now.ToString().Dump();
}

首先,在我的 Windows 時間設定中,完整時間的格式為 09:40:07 ,也就是 24 小時制。

現在讓我們先執行上面這段語法看看:

// 2021/10/04 21:00:00

接著讓我們變更時間格式看看。

以我的 Win10 為例,在 Windows 工具列,也就是畫面的右下角右鍵,選擇 調整日期時間 → 日期時間格式設定 → 變更資料格式,將時間格式變更為 上午 09:40:07

重新啟動 Linqpad 再執行如下:

// 2021/10/04 下午 09:00:00

可以看到 下午 兩個字就蹦出來了!

之所以會有這樣的差異,是因為 DateTime.ToString() 預設轉換的目標格式會是抓取目前執行緒的文化特性

……

閱讀全文


菜雞抓蟲: 使用 FromUri 的複雜型別在有傳遞 QueryString 的情況下會先建立再賦值

Image

事發緣由

在 .net Framework 4.6.2 MVC 的 ApiController 中,某個查詢資料列表的方法除了提供查詢條件的參數以外,還有提供選擇性的分頁參數。也就是像這樣子:

[HttpGet]
public IEnumerable<Boo> GetBoos(
    [FromUri] SearchBooParameter parameter,
    [FromUri] PagingParameter paging = null)
{
    // 呼叫 Service 查資料...
}

由於需要調整該功能的預設排序,改為由大到小,又不想背負更改大量共用的 PagingParameter 去影響到其他使用到的地方,決定在 Controller 這裡簡單用預測值加上判斷處理一下就好

相信著「若使用者沒有傳遞 paging 相關的參數,應該就會是給定的預設值 null 吧!」的我,用了 if (paging is null) 進行判斷:若是 null 的情況就將其中用來標示排序方向的成員 isDesc 設定為 true,開開心心交差。

[HttpGet]
public IEnumerable<Boo> GetBoos(
    [FromUri] SearchBooParameter parameter,
    [FromUri] PagingParameter paging = null)
{
    if (paging is null)
    {
        paging = new PagingParameter();
        paging.isDesc = true; // 預設由大到小
    }
    // 呼叫 Service 查資料...
}

但實際使用之後發現:即使只有傳入查詢條件參數、未傳遞 paging 時,資料仍然由小到大顯示,且 paging.isDesc 竟然是 false,並未被更改到。也就是說,即使未傳遞 paging,它也並不是 null!

實測之後發現:若在呼叫該 API 的時候,給定一個完全無關的參數,例如 ?a=1,則 paging 還是會被建立一個實體出來,並無視 = null 這個預設值。因此就導致了非預期(=跟我想的不一樣啊!)的行為。

這邊直接先講結論:如果有傳遞 QueryString 的任何參數時,不管這些參數跟指定的類別有沒有關係,放在 [FromUri] 的複雜型別都會先建立出實體,再嘗試和 QueryString 的內容進行比對與設值

設定在 [FromUri] 的複雜型別身上的預設值,像是 [FromUri] PagingParameter paging = null 只有完全沒給任何 QueryString 的時候才會吃到。(不過因為預設值只能是常數的關係,基本上就是指 defualt 的 null)

因此如果遇到要給定預設值的場合,還是得乖乖地針對型別中的成員做設定比較保險,例如 bool isDesc { get; set; } = true。另外,因為完全沒給 QueryString 的時候還是會是 null,故該有的參數檢查仍然不能漏了。

……

閱讀全文


菜雞抓蟲: Url 變得怪怪的?你可能是零寬空格(ZWSP)的受害者!

這週遇到個想不到的坑,特別來記錄一下。故事是這樣的--

在需要呼叫其他 API 服務時,發生了以下怪事:

  • 打某支查詢 API,突然查不到任何東西,或是跳出參數錯誤
  • 有些需要用參數組成 URL 的 API 跑出 Not Found
    • 第一組資料呼叫成功,第二組突然路徑錯誤
  • 寫入的時候,資料莫名其妙多了個 ?
    • 例如原先的資料是 ABC,不知怎地變成了 ABC?

由於這些操作都涉及到同一個參數,直覺上就是我們這邊給的參數出了點問題,馬上進入找犯人的環節。直接中斷點標記下去,反覆觀察該字串,但它就是一個普通的字串 "ABC",完全看不出什麼端倪。

正要覺得參數沒有問題的時候,赫然發現組出來的 Url 相當不對勁:在該參數的後方,多出了 %E2%80%8B 這串神秘東西!

當下我驚呆了,我們傳出去的 Url 裡,並不是預想的 /api/product/ABC,而是 /api/product/ABC%e2%80%8b!真是赤裸裸的背叛!這串鬼東西到底是什麼來頭?!

……

閱讀全文


菜雞抓蟲: 在 Amazon Linux AMI 安裝 .net Core 時卡在 Requires: openssl-libs

最近遇到在 Amazon Linux AMI 要安裝 .net Core 3.1 環境的時候,會一直跳出
Requires: openssl-libs 而無法安裝的問題,儘管明明已經有 openssl 了,但還是解析失敗找不到依賴,過程一直碰壁,因此在這邊紀錄一下。

過程中嘗試了安裝 openssl-libs(會找不到該套件)、下載 Dotnet 的 tar.gz ,再直接對執行檔下 Dotnet 指令起站台(雖然網站起得來,但執行者會是當下的登入身分,也就是 ‘’@連線進來的IP-伺服器位置,而非由本機執行。後續如果有連線資料庫等檢查權限的地方就很容易出錯)

最後在 Dotnet Core 的 issue 翻到這篇 Cannot install .NET Core 2.0 on Amazon Linux AMI 才成功解決。

首先先將 openssl-libs 的 SPEC 抓下來,然後給 RPM 建置一下。這兩句可以參考一下這篇 RPM 打包︰由一竅不通到動手濫用 (二) 的說明。

wget https://github.com/dotnet/core/files/2186067/openssl-libs-ami.spec.txt
rpmbuild --bb openssl-libs-ami.spec.txt
……

閱讀全文