發表文章

目前顯示的是 8月, 2022的文章

[C#] 將列舉轉換為 SelectListItem 下拉選單 (Enum To SelectListItem)

圖片
 實作 1. 列舉內容 public enum TestEnum { [Display(Name = "A", Description = "A")] A, [Display(Name = "B", Description = "B")] B } 2. 建立一個 Enum-Helper /// <summary> /// Enum-Helper /// </summary> public static class EnumHelper { /// <summary> /// 轉換為 SelectListItem 下拉選單 /// </summary> /// <returns></returns> public static IEnumerable<SelectListItem> ToSelectListItem<T>() where T : struct { var type = typeof(T); if (!type.IsEnum) { return null; } var result = Enum.GetValues(type) .Cast () .Select(x => new SelectListItem { Value = (x.ToInt()).ToString(), Text =$"Name:{x.GetN

[C#] 取得列舉 名稱 (Get Enum Name)

圖片
   實作: *需求: (1)需要取得列舉的名稱(Name) (2)依相對應的列舉,將Int 轉換為列舉的名稱(Name) 1.列舉內容 public enum TestEnum { [Display(Name = "A", Description = "A")] A, [Display(Name = "B", Description = "B")] B } 2. 建立一個 Enum-Helper /// <summary> /// Enum-Helper /// </summary> public static class EnumHelper { /// <summary> /// 取得列舉名稱 /// </summary> /// <param name="obj">列舉物件</param> /// <returns></returns> public static string GetName(this Enum obj) { var objName = obj.ToString(); var t = obj.GetType(); var fi = t.GetField(objName); var arrayDescription = (DisplayAttribute[])fi.GetCustomAttributes(typeof(DisplayAttribute), false); return arrayDescription == null ? string.Empty : arrayDescription[0].Name; } /// <summary&

[C#] 取得列舉 描述 (Get Enum Description)

圖片
 實作: *需求: (1)需要取得列舉的描述 (2)依相對應的列舉,將Int 轉換為列舉的描述 1.列舉內容 public enum TestEnum { [Display(Name = "A", Description = "A")] A, [Display(Name = "B", Description = "B")] B } 2.建立一個 Enum-Helper /// <summary> /// Enum-Helper /// </summary> public static class EnumHelper { /// <summary> /// 取得列舉描述 /// </summary> /// <param name="obj">列舉物件</param> /// <returns></returns> public static string GetDescription(this Enum obj) { var objName = obj.ToString(); var t = obj.GetType(); var fi = t.GetField(objName); var arrayDescription = (DisplayAttribute[])fi.GetCustomAttributes(typeof(DisplayAttribute), false); return arrayDescription == null ? string.Empty : arrayDescription[0].Description; } /// <summary&

[Visual Studio]位於網際網路或是限制區域上 或是檔案上標有 web 字樣 所以無法處理該檔案。若希望處理這些檔案 請移除 web 字樣。

圖片
若從「網頁」下載具有「安全性限制」的檔案,瀏覽器會插入名為 Web 標記的標記,以記錄頁面來源網站的安全性區域,MSBuild 遵守此安全性限制,因此會得到這樣的錯誤訊息: 「 位於網際網路或是限制區域上 或是檔案上標有 web 字樣 所以無法處理該檔案。若希望處理這些檔案 請移除 web 字樣。 」。 「 Couldn't process file 'path' due to its being in the Internet or Restricted zone or having the mark of the web on the file. Remove the mark of the web if you want to process these files. 」 解決方法: 如果可以信任內容沒有問題的話,可以從 [檔案總管] 解除封鎖單一檔案,以覆寫限制, (開啟檔案上的 [ 屬性 ] 視窗,然後 核取 [ 解除封鎖 ] )。 官方參考文件: MSB3821

[IIS] IIS執行時,發生拒絕存取路徑 問題

圖片
問題大概是這樣,站台的應用程式會在路徑資料夾建立,修改,讀取「實體檔案」,卻遇到錯誤「 System.UnauthorizedAccessException: 拒絕存取路徑 」,看這個錯誤訊息很明顯的就知道,是因為我們的「IIS AppPool」沒有server端的這個路徑資料夾的權限導致的。 解決方法: 1.對沒有權限的路徑資料夾點擊右鍵=>「安全性」=>編輯 2.點擊「新增」 3.輸入物件名稱=>點擊「檢查名稱」=>點擊確定 ps: MyAppPool改為你的AppPool名稱,若有查詢到物件會像下圖一樣,出現底線 4.修改權限,給「完全控制」,並按確定

[windows]office 帳戶錯誤

圖片
 今天遇到一個傻眼的問題,我訂閱了office365,不過可能因為之前有2016版的關係,導致出現「office 帳戶錯誤」的錯誤,一直處理不好,有點生氣。我想這可能是windows認證的bug吧,爬了一下文,發現可以用「Microsoft支援及修復小幫手」來解決問題。 解決方法: 1.下載「 Microsoft支援及修復小幫手 」,並安裝 2.選擇「Office 與 Office 應用程式」 3.選擇第二點,並照著指示的步驟走,解決問題 ps:一個小坑,在執行步驟的時候要注意看說明,不要急著按下一步,我第一次執行的時候就沒注意到 要先將Office 裡的 帳戶先登出 ,導致失敗。

[C#,windows]設定windows環境變數,與自動切換SectionGroup 取得需要的appSetting資料

圖片
 寫好的程式,有時候可能部屬到不同的環境上,而有時候不同環境還有可能搭配不同的參數,此時寫在web.config的參數要如何切換不同環境取得不同參數值呢? 這邊提供一個思維,首先我們在各個環境上都建立一個環境變數,讓我們程式可以辨認目前是在哪一個環境上(若此環境變數未建立,預設是本機環境),並在web.config上建立「sectionGroup」,給予不同的「appSettings」值,如此一來便可以達到需求效果。 實作: 1.設定系統環境參數      (1)以系統管理員開啟PowerShell    (2)輸入欲設定的環境變數   <!--本機--> [environment]::SetEnvironmentvariable("Test_STAGING", "Dev", "Machine")   <!--客戶正式機--> [environment]::SetEnvironmentvariable("Test_STAGING", "pr", "Machine")   <!--客戶測試機--> [environment]::SetEnvironmentvariable("Test_STAGING", "qa", "Machine")   <!--公司測試機--> [environment]::SetEnvironmentvariable("Test_STAGING", "ta", "Machine") ps:「 Test_STAGING 」是環境變數名稱,可以隨意取,Dev,pr,qa,ta通常代表本機,客戶正式機,客戶測試機,公司測試機可以依環境選擇設定,這邊範例選擇設定的是本基環境。 *檢查是否有設定成功 [environment]::GetEnvironmentVariable('Test_STAGING', "Machine") *方法二 在 進階系統設定 設定環境變數 2.建立 終端解析 Helper /// <summa

[C#]this method is obsolete it has been replaced by system.configuration

之前遇過一個警告 「 'System.Configuration.ConfigurationSettings.AppSettings' is obsolete: '"This method is obsolete, it has been replaced by System.Configuration!System.Configuration.ConfigurationManager.AppSettings"' 」 其實放著不理也不會有什麼問題,但是看著就很煩,所以還是把過時的方法改掉比較好。 解決方法: 將 ConfigurationSettings.AppSettings["KeyName"] 改為 ConfigurationManager .AppSettings[" KeyName "] 參考: 'System.Configuration.ConfigurationSettings.AppSettings' is obsolete

[windows]排程工作器 簡單設定介紹

圖片
排程可以處理掉一些例行性,與重複性高的工作,因此在這個行業裡,無論如何總有一天會需要用到排程,這邊大致介紹一下windows「工作排程器」的使用方法。 實作: 1.在搜尋列 輸入「排程工作」並開啟 2.點擊「建立工作」 3.「一般」設定 *「名稱」可以隨便填 *「描述」可填可不填 *請選擇「不論使用者登入與否均執行」選項,這樣才不會在使用者登出後排程不執行 *若排程執行的程式,需要最高使用者權限,需勾選「以最高權限執行」 4.「觸發程序」設定:點擊「新增」=>設定排程執行週期(圖中的(2)可以設定排程在一日中的開始執行時間) 5.「動作」設定:點擊「新增」=>「瀏覽」,並選擇要執行的應用程式 6.後面的「條件」,「設定」大致上不用修改,都設定完成後點擊「完成」即可。

[Git]SSL certificate problem: certificate has expired Completed with errors, see above.

圖片
 近日在sourceTree推拉版的時候,遇到錯誤訊息: git -c diff.mnemonicprefix=false -c core.quotepath=false --no-optional-locks fetch --no-tags origin fatal: unable to access 'https://.git/': SSL certificate problem: certificate has expired Completed with errors, see above. 大概就是GitLab的憑證過期導致的,所以沒辦法,只能先關掉Git的SSL驗證應急一下。 解決方法: 在Terminal輸入指令 關閉SSL驗證: git config --global http.sslVerify false ps:在推拉版之後記得再度將SSL驗證開啟: git config --global http.sslVerify true

[windows] robocopy 備份至 網路磁碟機

圖片
  實作: 來源: D:\develop ;目標: Z:\develop ;檔案數:48120 1.新增網路磁碟機,作法請參考這篇「 檔案歷程記錄 備份至 網路磁碟機 」的步驟1至步驟3 2.cmd執行robocopy ,或是將指令轉為「批次檔 .bat」執行 我依我這邊的需求,組成我需要的指令: robocopy官方文件 (1)cmd: ROBOCOPY D:\develop Z:\develop /R:0 /W:0 /E /TEE /NFL /NDL /XO /xa:h (2).bat: 「批次檔,這邊我想每次執行時可以寫一個用時間為檔名的LOG,指令如下。 set today=%date:~0,4%-%date:~5,2%-%date:~8,2% set filename=%today%_%time:~0,2%%time:~3,2%%time:~6,2%.txt set sourcePath=D:\ set targetPath=Z:\ robocopy %sourcePath%develop %targetPath%develop /R:0 /W:0 /E /TEE /NFL /NDL /XO /XA:H /MT:32  >>D:\xcopyLog\%filename% ps: /R:n 失敗複本的重試次數: 預設值是 1 百萬次。 /W:n 重試之間等候時間: 預設值是 30 秒。 /E 複製子目錄,包括空的子目錄。 /TEE 輸出至主控台視窗,以及記錄檔。 /NFL 沒有檔案清單 - 不記錄檔案名稱。 /NDL 沒有目錄清單 - 不記錄目錄名稱。 /XO 排除較舊的檔案。 /xa:[RASHCNETO] 排除已設定任何指定屬性的檔案。 此選項的有效值為:         • R - 唯讀         • A - 封存         • S - 系統         • H - 隱藏         • C - 壓縮         • N - 未編制索引的內容         • E - 加密         • T - 暫存         • O - 離線 /MT:32 — 使用 n 個執行緒進行多執行緒複製(預設值為 8)。必須至少為 1,但不得大於 128。 *依我的觀察MT,如果單一檔案

[windows] xcopy 備份至 「網路磁碟機」

圖片
 實作: 來源: D:\develop ;目標: Z:\develop ;檔案數:42966 1.新增網路磁碟機,作法請參考這篇「 檔案歷程記錄 備份至 網路磁碟機 」的步驟1至步驟3 2.cmd執行xcopy ,或是將指令轉為「批次檔 .bat」執行 我依我這邊的需求,組成我需要的指令: xcopy官方文件 (1)cmd: XCOPY D:\develop Z:\develop /D/K/E/Y/C/I/J (2).bat: 「批次檔,這邊我想每次執行時可以寫一個用時間為檔名的LOG,指令如下。 set today=%date:~0,4%-%date:~5,2%-%date:~8,2% set filename=%today%_%time:~0,2%%time:~3,2%%time:~6,2%.txt set sourcePath=D:\ set targetPath=Z:\ echo **************************>>D:\xcopyLog\%filename% echo start Time:%date:~0,4%-%date:~5,2%-%date:~8,2% %time%>>D:\xcopyLog\%filename% echo sourcePath:%sourcePath%>>D:\xcopyLog\%filename% echo targetPath:%targetPath%>>D:\xcopyLog\%filename% echo **************************>>D:\xcopyLog\%filename% XCOPY %sourcePath%develop %targetPath%develop /D/K/E/Y/C/I/J>>D:\xcopyLog\%filename% echo End Time:%date:~0,4%-%date:~5,2%-%date:~8,2% %time%>>D:\xcopyLog\%filename% echo **************************>>D:\xcopyLog\%filename% ps: /D只複製比目的檔還新的檔案  /K複製後檔案屬性不變, /

[windows]檔案歷程記錄 備份至 網路磁碟機 backup using file history

圖片
 實作: 假設我們現在有一個server A,跟server B,情境大概是要將server A的某個目錄備份至server B。 (ps:這邊雖然叫server A,不過實際上我發現windows server 沒有 利用檔案歷程記錄備份 的服務,看來是只有 windows10or11的作業系統才有) 1.在server B 控制台=>網路共用中心=>變更進階共用設定 開啟網路探索,開啟檔案及印表機共用([關閉以密碼保護]不關的話,就是要輸入使用者帳密) 2.在server B建立一個共用資料夾「ScottTest」 並開權限給Everyone 讀取/寫入 3.在server A建立 網路磁碟機 連線至 server B 的 共用資料夾「ScottTest」 4.在 server A 搜尋備份設定=>新增磁碟機 5.選擇要備份的目錄 參考文獻: 網路芳鄰設定 新增網路磁碟機 備份還原

[C#] 設定 與 取得 Cookie

圖片
在寫Web的時候,如果有遇到存參數的情境,若非權限相關的資訊,儘量能存在client端,就存在client端,畢竟Server的空間也有限,所以能省則省。那麼這時候對Cookie做設定與取得就會變成常態,因此建議可以寫個Extension來做處理。 範例: 1.建立一個Controller-Extension /// <summary> /// Controller-Extension /// </summary> public static class ControllerExtension { /// <summary> /// 設定 Cookice /// </summary> /// <param name="controller"></param> /// <param name="cookieName"></param> /// <param name="data">object</param> /// <param name="timeOutMin">time out 時間(單位:分)</param> public static void SetCookice(this Controller controller, string cookieName, object data, int? timeOutMin = null) { var js = new JavaScriptSerializer(); var cookie = new HttpCookie(cookieName) { Value = js.Serialize(data), // 設定預設路徑 避免Cookie自行設定路徑

[C#]google oauth JWT is not yet valid

圖片
 如果伺服器與Google服務器的系統時間不同,當我們在驗證從Google收到的令牌時,可能會得到Exception「JWT is not yet valid」,此時大概有兩種解決方法,1.調整伺服器時間到世界標準時間;2.建立一個 IClock Class,在 ValidateAsync() 方法中傳遞一個時鐘(因為實務上可能很難對伺服器做修改,所以還是乖乖改code吧)。 解方方法2 範例: 1.建立一個繼承 IClock的類別 public class clock : IClock { public DateTime Now => DateTime.Now.AddMinutes(5); public DateTime UtcNow => DateTime.UtcNow.AddMinutes(5); } 2.在驗證Token的時候 傳遞一個時鐘 // 驗證憑證 var settings = new GoogleJsonWebSignature.ValidationSettings() { Clock = new clock(), Audience = new List () { GoogleClientId } }; GoogleJsonWebSignature.Payload payload = GoogleJsonWebSignature.ValidateAsync(formCredential, settings).Result; 相關文章: [C#] MVC 實作 Google OAuth

[Json]判斷 資料 是否已存在 Json字串內,是 則更新字串,否 則將資料加入字串

圖片
 有時候資料庫設計並不會特定開張表來儲存「使用者變更的欄位資訊」,我遇過幾個SD的設計是將「使用者變更的欄位資訊」轉換為一個JsonString再存入資料庫的一個欄位裡面(有點no sql的感覺,就是在做欄位變更的時候可能會比較方便)。 這時候我們就會很常遇到要對JsonString做新增修改的動作,因此我就想寫一個JsonHelper,可以來對JsonString的編修做處理。 範例: 這支JsonHelper主要的設計是將「資料庫的JsonString (List)」與 「有要編修的資料Data(單筆)」做比對,並判斷這筆Data對JsonString來說是Add還是Edit,那如何判定是Add還是Edit呢?這邊我多加一個參數「comparisonparamName」也就是要比對的屬性名稱,如果FindIndex在JsonString內有比對到跟Data相同的資料則代表是Edit。 1.測試用模型 public class JsonTestModel { public string Name { get; set; } public string Value { get; set; } } 2.JsonHelper Code /// <summary> /// Json Helper /// </summary> public static class JsonHelper { /// <summary> /// Upadte Json Data List by data And Comparison Parameter Name /// </summary> /// <typeparam name="T"></typeparam> /// <param name="jsonString">Json Data List(string)</param> /// <param name="data">(upd

[Dapper] Get Output Value

圖片
 近來專案上遇到,預存程序有Output的情況,踩了一點雷,在這邊紀錄一下。 大致上的流程是要先建立一個 DynamicParameters ,將預存程序會用到的參數都篩進去,然後是Output的參數要特別處理(direction要給 ParameterDirection . Output ),這樣在 conn . Query ()之後就可以在我們原先建立的 DynamicParameters 裡取得Output的值了。 ps:請注意在 DynamicParameters . Add ()的時候,若sql有限制參數大小 如:varchar(10),記得給size,且 direction 一定要給 ParameterDirection . Output ,否則可能會有Exception或者取回空值得情況發生。 範例: 1.先建立一個  DynamicParameters 產生器,來產生預存程序會用到的參數 /// <summary> /// DynamicParameters-Builder /// </summary> public class DynamicParametersBuild { public DynamicParameters Data { get; set; } public DynamicParametersBuild(object data) { OriginalBuild(data); } /// <summary> /// Original Build DynamicParameters /// </summary> /// <param name="data">data</param> private void OriginalBuild(object data) { var parameters = new DynamicParameters(); var properties

[C#] Microsoft Anti-XSS (Anti-Cross Site Scripting Library) 避免XSS攻擊

圖片
 為了防止XSS攻擊(攻擊者可能利用<input>寫入<script>字串,而造成安全上的危害),因此最好的做法就是過濾掉可能有問題的資串,Microsoft.Security.Application的GetSafeHtmlFragment()就是其中一個方法。 範例: 1.測試程式碼 //測試 有危害內容的字串 var testString = "<script>alert(1);</script>TestName"; Console.WriteLine($"原始字串:{testString}"); //字串過濾 var rsult = Sanitizer.GetSafeHtmlFragment(testString.Trim()); Console.WriteLine($"過濾後字串:{rsult}"); Console.ReadLine(); 2.結果

[JQuery]列印包含css 的div-jqprint

圖片
在開發網站的時候很常會遇到需要印列頁面的需求,以往常用的做法是在列印時,將不想列印的部分隱藏,或者另開一個頁面直接將想列印的部分的html寫入並列印,不過這些做法都很麻煩,而且會有css引用的問題,導致跑版之類的。 所以今天想介紹一下「jqprint」,在開發上真的會方便很多。 範例: 1.html code(拿「傳統」作法跟「jqprint」做個比較) <table class="table table-bordered landTable tabbleNarrow table-center table-vert-center" id="PrintDiv"> <tr> <td>Test1</td> <td>Test2</td> </tr> </table> <button onclick="NormalPrint()">NormalPrint</button> <button onclick="JQueryPrint()">JQueryPrint</button> @section scripts { <script src="~/Scripts/custom/jqprint.js"></script> <script> function NormalPrint() { w = window.open(); w.document.write($('#PrintDiv').html()); w.print(); w.close(); } function JQueryPrint() { $("#PrintDiv").jqprint(); } </script> } 2.jqpri