solve UTF8 Encoding at ASP.NET and Claude Code
環境
作業系統:Windows
開發軟體:Visual Studio 2022
.Net 版本:.Net Framework 3.5 ~ 4.8
Claude Code 版本:v2.0.28
背景
最近維護 ASP.NET WebForm 的古蹟網站(.aspx),使用 Claude Code 幫忙開發專案,遇上程式碼檔案的UTF8編碼相容問題
原因
Visual Studio 2022 在 Windows 作業系統下,預設建檔、寫檔都使用UTF8 with BOM編碼,但是 Claude Code 預設使用 UTF8 編碼來寫入檔案。
※Visual Studio Code行為不太一樣,Visual Studio Code 預設建檔使用UTF8編碼、寫檔自動偵測。
上網爬文貌似 Windows 作業系統 + 微軟軟體,大部份都使用 UTF8 with BOM 來讀寫檔案(包含 Excel),和 Linux 環境不一樣。
造成錯誤
1.經過 Claude Code 寫檔過的 .aspx 網頁,網頁一執行會有亂碼
2.經過 Claude Code 寫檔過 .cs 程式碼,中文命名的變數與函數會讓 msbuild指令編譯錯誤 或 其它程式碼調用的時候找不到要呼叫的對象(因為變成亂碼了)。
解決方案
兩種解決方法:
1.調整 Visual Studio 寫檔的編碼為UTF8 以支援 Claude Code
2.調整 Claude Code 寫檔的編碼為UTF8 with BOM 以支援 ASP.NET (.Net Framework) 網站的開發
※已實測,ASP.NET 9 不管 UTF8 或 UTF8 with BOM,兩者編碼的檔案併存於同一專案裡都能正常編譯&顯示,也就是說你如果使用 ASP.NET 最新技術開發網站的話,應該和 Claude Code 能夠相處融洽。
實作
1. 調整 Visual Studio 寫檔的編碼為UTF8
在 Visual Studio 的方案目錄下,新增一個 .editorconfig 檔案來定義 Visual Studio 為指定副檔名的檔案使用UTF8編碼來寫檔
[*.{cs,vb,aspx,cshtml,txt,html,htm,css,js,json,yaml,xml,config,ini,sh,ps1,csproj,vbproj,sln,gitignore,gitattributes,editorconfig,md,markdown,py}]charset = utf-8

※留意僅管使用此方法,Visual Studio在建立新檔案時,仍然為預設的UTF8 with BOM編碼,你必須再透過Visual Studio編輯/寫檔,該檔案才會變成 .editorconfig 指定的編碼
最後 Web.config 加入以下設定就完成了
<system.web>
<!--讓 .aspx、.cshtml 網頁正常顯示 UTF-8 編碼的文字 -->
<globalization fileEncoding="utf-8" />
</system.web>此解決方案適用情況:
1.跟你一起寫 Code 的同事使用 Mac、Linux 作業系統,程式碼需要 UTF8 編碼來跨平台相容編輯
2.覺得讓 Claude Code 額外把 UTF8 編碼的檔案轉換成 UTF8 with BOM 的效率太慢(第二種解決方案)
如果你想讓ASP.NET 9的工作專案裡的檔案都統一使用UTF8編碼,此方法也是可以使用。
以下介紹另一個解決方案
2. 讓 Claude Code 使用UTF8 with BOM寫檔
由於 Claude Code 預設使用 UTF8 編碼寫檔,如果透過提示詞、記憶檔(User Memory)特別要求它使用 UTF8 with BOM 編碼來寫檔的話,
我自己是遇到以下兩種狀況:
1.Claude Code額外使用 Powershell 把寫完的檔案轉換成UTF8 with BOM,但每次 Powershell 腳本都寫得不一樣、不太穩定
2.Claude Code有時候會忘記&漏掉要做編碼轉換,誤以為 UTF8 就已經是 UTF8 with BOM,然後很有自信地回報我工作處理完畢…
所以這邊我使用 Claude Code Hooks 呼叫事先準備好的 Powershell 腳本檔案(.ps1) 執行編碼轉換,
確保 Claude Code 每次 Write/Edit 檔案完畢後,一定都會執行檔案編碼的轉換動作。
2-1. 以下是 Powershell 腳本內容
官網文件範例是 Python 和 Typescript ,但我用 Powershell 腳本是因為我電腦是 Windows 作業系統,再加上它不像 .exe 要先經過編譯才能執行,
選個自己方便的腳本好執行即可。
# 把檔案轉換成 UTF-8 with BOM 編碼的腳本
# 定義允許要轉換的副檔名白清單
$allowedExtensions = @('.cs', '.vb', '.aspx', '.cshtml', '.html', '.htm', '.css', '.js', '.txt', '.config', '.json', '.ps1', '.md')
# 從 Console 標準輸入(Claude Code傳遞的參數)取得 JSON 字串
$inputJson = [Console]::In.ReadToEnd()
# 將 JSON 字串轉換為 JSON 物件
$objJson = $inputJson | ConvertFrom-Json
# 取得 file_path 的值 ( Claude Code 叫用內部工具會傳入要寫檔的檔案路徑)
$filePath = $objJson.tool_input.file_path
# 取得檔案名稱
$fileName = [System.IO.Path]::GetFileName($filePath)
# 取得副檔名(轉小寫方便比較)
$fileExtension = [System.IO.Path]::GetExtension($fileName).ToLower()
# 檢查副檔名是否在允許清單中
if ($allowedExtensions -notcontains $fileExtension) {
# 無須處理,離開腳本並回傳成功狀態碼
exit 0
}
# 通過白名單副檔名檢查,需要進行編碼轉換
# 讀取檔案內容,使用 -Raw 參數以取得完整內容並當作一個字串
$content = Get-Content -Path $filePath -Raw -Encoding UTF8
# 建立帶 BOM 的 UTF8 編碼器
$utf8BOM = New-Object System.Text.UTF8Encoding $true
# 重新寫入檔案 (帶 BOM)
[System.IO.File]::WriteAllText($filePath, $content, $utf8BOM)
`$filePath = $objJson.tool_input.file_path`:Claude Code 執行內部工具觸發 Hooks 會傳遞給你的 Powershell 參數請參考官網↓

Powershell腳本我儲存在 Claude Code 的 User Memory (CLAUDE.md)所在目錄,供各專案使用。
記得檔案另存編碼為 UTF8 with BOM,因為 Powershell 是微軟的技術。

2-2. 在 Claude Code 的 設定檔(settings.json) 加入以下 hooks 的設定
"PostToolUse":Claude Code 的內部工具執行完畢之後。
指定matcher當建立(Write)檔案、編輯(Edit)檔案之後,要觸發 cmd指令(目前也只有"type": "command")
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "powershell -ExecutionPolicy Bypass -File C:/Users/shadow/.claude/ConvertTo-Utf8BOM.ps1"
}
]
}
]
}
}留意幾點:
"matcher":英文官方文件最新版已經沒有 MultiEdit 這個參數,哪天參數 Edit 改名稱叫 Update 也不意外(因為我看目前版本的 Claude Code 內部工具在編輯檔案用的是 Update 指令)
"command": "powershell -ExecutionPolicy Bypass C:/Users/shadow/.claude/ConvertTo-Utf8BOM.ps1 yourParam":
這段 command 最後面若有想要傳入你自己的參數(yourParam),這帶入的參數會是常數變量,從 settings.json 設定檔是無法取得 Claude Code 呼叫它內部工具時的參數,
因為 Claude Code 會傳遞的參數目前都放在 Console 的標準輸入裡,須透過執行腳本這類方法才能取得。(請參考上述的 Powsershell 的 `[Console]::In.ReadToEnd()`)
settings.json:Claude Code 的設定檔,不能寫入英文或中文註解,否則會無法套用。
每當設定檔編輯完畢,必須重新啟動 Claude Code,讓它重新載入 settings.json 才會生效。
設定檔的hooks視自己需求看是要寫在全域或是專案的 settings.json,生效的作用範圍不一樣:全域設定檔→Claude Code 的每個工作專案都生效;專案設定檔→僅限該工作專案。
以下圖片是設置在專案設定檔。啟動 Claude Code 的目錄通常也是 Visual Studio 的方案目錄

settings.json記得編碼要另存成 UTF-8 ,因為是 Claude Code 使用
Claude Code 的 Hooks 解決方案適用情況:
一人獨自開發、環境單純好掌握、公司全員同事都使用 Windows 作業系統、沒有想要跨平台、
程式碼檔案通通使用 UTF8 with BOM 編碼也無妨的重度使用微軟技術的工程師
結語
以上,挑選適合自己的解決方案使用
參考文章
Claude Docs 官方文件:Hooks reference