ShowProgramCode

2021年12月3日 星期五

MS SQL工具改變資料表欄位自動增值失敗問題

今天我發現資料庫沒有建立主Key,且主Key欄位非自動增值造成我新增資料失敗後,便來調整資料庫的欄位設定。 

使用的工具是Microsoft SQL Server Management Studio。

不過當我把主Key調整好,設定自動增值如下圖:

將設定存檔時卻發生錯誤無法調整,如下圖:


最終在同事的幫忙下發現,這個錯誤訊息必須調整『工具』選項中的『設計師』中,把『防止儲存需要資料表重建的變更』這項設定取消。如下圖:













這樣就可以調整資料表的主Key欄位並讓它自動增加數值了。



2021年11月25日 星期四

改變.NET Framework版本

 如何不透過UI直接從檔案更改Framework版本?

原先我都是利用Visual Studio的介面更改Framework的版本,不過這次的專案不知為何改變版本後,Web Reference就發生錯誤,甚至無法編譯。

本來應該設法好好找出Web Reference就發生錯誤的原因,不過由於時程問題,我想到如果不透過介面直接從檔案更改Framework版本,是否可以避免因為重新讀取專案檔,系統檔改寫後編譯錯誤的問題。

終於,那麼更改Framework應該從哪個系統檔處理呢?

基本上就是.csproj檔案。

在這個檔案內容可以找到Framework目前的版本,直接修改版本號碼就可以改變Framework版本。

改變.sln專案檔版本

如何將.sln專案檔提升至2017版本

最近遇到客戶提出了這個要求,順便參考官方文件的說法,整理一下如何提升專案檔版本?

參考網站:https://docs.microsoft.com/zh-tw/visualstudio/extensibility/internals/solution-dot-sln-file?view=vs-2017


先不考慮專案內容是否會有衝突的問題,單純紀錄該如何修改.sln版本。

依照官網文件的說法,基本上相當簡單,只要修改檔案的表頭即可。

下列附上每個不同VS版本的.sln表頭。

  • VS2022

Microsoft Visual Studio Solution File, Format Version 12.00

# Visual Studio Version 16

VisualStudioVersion = 16.0.28701.123

MinimumVisualStudioVersion = 10.0.40219.1


  • VS2019

Microsoft Visual Studio Solution File, Format Version 12.00

# Visual Studio Version 16

VisualStudioVersion = 16.0.28701.123

MinimumVisualStudioVersion = 10.0.40219.1


  • VS2017

Microsoft Visual Studio Solution File, Format Version 12.00

# Visual Studio 15

VisualStudioVersion = 15.0.26730.15

MinimumVisualStudioVersion = 10.0.40219.1


  • VS2013

Microsoft Visual Studio Solution File, Format Version 12.00

# Visual Studio 2013

VisualStudioVersion = 12.0.40629.0

MinimumVisualStudioVersion = 10.0.40219.1

VS2022與VS2019的設定表頭設定基本是相同的,關於這個我暫時沒有找到更詳細的說法,因為我最近修改的版本為VS2013 => VS2017,經過修正之後,客戶那邊確認可以使用。

將官網針對表頭的說明複製上來,若有侵權疑慮請先告知,謝謝!


Microsoft Visual Studio Solution File, Format Version 12.00
定義檔案格式版本的標準標頭。

# Visual Studio 15
Visual Studio 的主要版本, (最近) 儲存此方案檔。 這項資訊會控制解決方案圖示中的版本號碼。

VisualStudioVersion = 15.0.26730.15
Visual Studio 的完整版本, (最近) 儲存的方案檔。 如果解決方案檔是由具有相同主要版本的較新版本 Visual Studio 所儲存,則不會更新此值,以便減少解決方案檔中的流失情形。

MinimumVisualStudioVersion = 10.0.40219.1
可以開啟此方案檔之 Visual Studio 的最小 () 版本。

也就是說,基本上只要置換中間兩行就能將.sln版本更換。

# Visual Studio 15

VisualStudioVersion = 15.0.26730.15

查詢此問題時,還有看到可以將專案拷貝各種不同版本的.sln檔案,方便使用不同的VS版本開啟的說法。

通常專案檔版本還是需要配合客戶需求,所以更改版本是有機會發生的問題,特別記錄下來。


2021年9月7日 星期二

C# ASP.NET web.config的RSA加密

 通常我們會在web.config中放入很多設定值,其中不乏帳密之類的機密資料。按理說,這支檔案是無法被截取的,不過為了安全起見,倘若可以做更多加密處理,也能更加放心。

這次客戶提供的web.config就有加密處理,並且因為沒有RSA Key的原因,整個程式無法順利編譯。因此我將這個RSA加密web.config的方式記錄下來。

使用RAS Key加密,必須用到Visual Studio的一個執行檔(aspnet_regiis.exe),所以必須將cmd用管理者權限執行後,將路徑移動到那個執行檔的資料夾。

C:\Windows\Microsoft.NET\Framework\v4.0.30319,這是我使用的資料夾。

在HelloWorld中加上讀取appSettings的內容,確認加密前後程式可以正常編譯。



















[WebMethod]

public string HelloWorld()

{

    string temp = ConfigurationManager.AppSettings["test"];

    return temp;

}


一、以本機的RSA Key加解密:

這個方法比較簡單,不過一旦將檔案移到別的主機上,就會發生最前面所述,整個程式無法編譯的問題,所以自己玩一下可以,並不是那麼實用。

加密:

1.在命令列執行aspnet_regiis.exe -pef appSettings "專案的web.config所在資料夾"

以本機RAS Key加密





2.確認web.config加密後內容

web.config加密後內容
















3.編譯執行程式,看看是否可以順利讀到appSettings內容

解密:

1.在命令列執行aspnet_regiis.exe -pdf appSettings "專案的web.config所在資料夾"

以本機RAS Key解密






2.確認web.config是否解密還原最初的內容

二、以固定的RSA Key加解密

1.確認使用本機或是取得其他RSA Key加密

    1.1使用本機的RSA Key加解密

    這應該是最常見的狀態,使用本機的RSA Key加密後,提供這把Key給其他使用者。

aspnet_regiis.exe關於說明建立RSA Key說明


參考上述的說明內容,在命令列執行aspnet_regiis.exe -pc "金鑰名稱" -exp,如下圖。

在命令列執行建立RSA金鑰







之後修改專案的web.config內容,加入一段設定指定金鑰加密的部分。

<configProtectedData>

    <providers>

      <add name="RuitingtechProvider" type="System.Configuration.RsaProtectedConfigurationProvider,System.Configuration, Version=4.0.0.0,  Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" keyContainerName="金鑰名稱" useMachineContainer="true"/>

    </providers>

  </configProtectedData>

web.config設定特定RSA金鑰加密





在命令列輸入加密命令,aspnet_regiis.exe -pef 加密區段 "web.config資料夾路徑" -prov "RuitingtechProvider"

在命令列輸入使用特定RSA金鑰對web.config特定區域加密




web.config加密後內容


















   
    1.2使用其他裝置密鑰加密
    這邊就不特別實作,大致應該是把金鑰檔匯入本機中,其他的動作應該是差不多的。

確認加密後程式可以正常編譯、執行。

2.確認使用本機或取得其他RSA Key解密
    2.1使用本機特定金鑰解密
    在命令列輸入解密命令,aspnet_regiis.exe -pdf 解密區域 "web.config所在資料夾路徑"
在命令列輸入解密命令









    web.config恢復未加密內容。

    2.2使用其他裝置密鑰解密
    這邊不特別實作,先將金鑰匯入本機中,其他動作應該是差不多的。
將其他裝置金鑰的xml匯入命令參考







3.將RSA Key匯出xml檔案給其他裝置使用
aspnet_regiis.exe -px “金鑰名稱” 金鑰xml路徑 -pri
在命令列輸入匯出xml檔案命令








尋找一下這個位置是否產生了xml的金鑰檔案。



最後補充一下刪除金鑰容器的說明。
 aspnet_regiis -pz "金鑰名稱"




參考網頁:
https://dotblogs.com.tw/wasichris/2016/01/01/235040
https://www.itread01.com/content/1549832402.html
以及C# Asp.Net官方文件


2021年9月1日 星期三

C# ASP.NET的DEBUG模式下執行特定程式

 今天把程式放上IIS後,居然出現在本機測試沒有出現的Error。去查了LOG,回到程式碼查看後,發現程式跑了一段我在本機處理時不曾跑過的函式,函式中需要驗證的機器因為沒有設定,所以才出現了Error。

但是為什麼在本機測試時,一直沒有出現這樣的錯誤呢?

程式中出現了下面的內容,於是我上網去查了C#的說明。

#if(!DEBUG)

.......

#endif

直接先說結論,這段程式的意思大致是,程式在非Debug模式下執行,會進入裡面的內容。而我在本機一直是用Debug模式在執行程式,所以才沒有發現這個問題。

這其實是個好用的設定,偶爾我們需要在Debug的模式下特別紀錄某些LOG或者特別執行某些程式來做測試,利用這個的功能就可以不調整程式的前提下,將一般模式與Debug模式分開處理。

要如何設定這個功能呢?

首先,在web.config中確認<compilation debug="true"/>這個設定是正確的。

接著關於如何判斷是否在Debug模式下,則有兩種做法。

1.如上方所述,利用#if(DEBUG)判斷:

將所有要在DEBUG模式下執行的程式,放在#if(DEBUG)與#endif之間即可,比較直觀,但是之後修改不易,可能讓程式中佈滿相關的if。一旦要修改也很難找到正確的修改位置。

2.利用 ConditionalAttribute 屬性來判斷:

這部分我目前尚未實測過,不過相較之下看起來比較容易將相關的程式放在一起,之後維護起來也比較方便。

在DEBUG模式下要處理的函式加上[Conditional("DEBUG")]即可,參考如下。

[Conditional("DEBUG")]
Public void DebugLog()
{
......
}

日後有需要我應該會採用第二種做法,有時間也可能做個測試程式。

參考網頁如下:
https://dotblogs.com.tw/joysdw12/2014/03/14/asp-net-debug-release-if-else-conditional

2021年5月10日 星期一

重灌window後,Asp.Net的專案無法執行了

 很不幸,周末去檢查確定我的電腦硬碟可能快不行了,只好重灌windows,然後把所有的檔案拉到USB裡面。

但是今天上班後,重新執行卻發現Visual Studio無法執行。

錯誤代碼大致有"HTTP 錯誤 500.19 - Internal Server Error"、"無法存取要求的網頁,因為與該網頁相關的設定資料不正確"、"無法讀取設定檔案,因為權限不足"。

後來查了資料才確定是因為專案中的.vs資料夾內會和新OS產生衝突,只要把.vs資料夾殺掉,然後重新執行就可以了。

雖然是一場烏龍,不過仍然要記下來,提醒自己下次注意。

備註:版控的ssh密鑰也需要重設(哭)。

2021年5月3日 星期一

C# 如何取得 Enum 的 Description 描述字串

 看了很多資料,不過到最後還是搞不清楚,所以實作看看。

最後建立一個靜態物件,暫時放在專案資料夾最外層。

然後寫了一個測試檔,可以順利讀取到Enum的Description描述字串。

最開始希望能用Enum.Field.GetDescription(),不過沒有成功,如果之後找到其他方法可能會繼續補充。


程式碼:

public static class EnumHelp

    {

        public static string GetDescription(this Enum value)

        {

            Type type = value.GetType();

            string name = Enum.GetName(type, value);

            if (name != null)

            {

                System.Reflection.FieldInfo field = type.GetField(name);

                if (field != null)

                {

                    DescriptionAttribute attr =

                           Attribute.GetCustomAttribute(field,

                             typeof(DescriptionAttribute)) as DescriptionAttribute;

                    if (attr != null)

                    {

                        return attr.Description;

                    }

                }

            }

            return null;

        }

    }

測試碼:

public enum TestEnum

    {

        [Description("Test001")]

        One = 1,


        [Description("Test002")]

        Two = 2,


        [Description("Test003")]

        Three = 3

    }


    [TestClass]

    public class DemoTest

    {

        [TestMethod]

        public void EmunHelpTest()

        {

            string enumOneDescriptionChk = "Test001";

            string enumTwoDescriptionChk = "Test002";

            string enumThreeDescriptionChke = "Test003";


            string enumOneDescription = EnumHelp.GetDescription(TestEnum.One);

            Assert.AreEqual(enumOneDescription, enumOneDescriptionChk);


            string enumTwoDescription = EnumHelp.GetDescription(TestEnum.Two);

            Assert.AreEqual(enumTwoDescription, enumTwoDescriptionChk);


            string enumThreeDescription = EnumHelp.GetDescription(TestEnum.Three);

            Assert.AreEqual(enumThreeDescription, enumThreeDescriptionChke);

        }

    }

C#中同一方案中不同專案共用libary

 如題,我做這個案子時,發現四個專案內有許多物件、函式非常相像。

不希望維護多個類似的程式碼,所以我想要把四個專案拉進同一個方案中,然後再加一個專案,專門放共用的函式庫以及測試碼。

最終成功的方法,要將所有專案放入同一個方案,然後把共用的那個專案在另外四個專案中設置「參考」。

之後便可以在那四個專案中,呼叫到被參考的共用專案中的所有檔案。

下面我用了另一個Demo來截圖表示,裡面只有兩個專案,是為了自己忘記這個方法的備註。

第一是方案總管截圖,可以看到這個Demo的結構。


圖二顯示Demo02的參考內容


圖三是Demo01的主程式

圖四是Demo02的主程式


2021年4月23日 星期五

C#中DTO資料傳給另一個DTO

 最近換了工作,所以要開始寫ASP.NET了,C#和PHP的差異不小,因此寫起來有點...

遇到問題是一定的,決定開始慢慢建構自己的C#筆記。

不過對於C#而言,我還是個新手,如果有什麼錯誤還請多多包容。

今天遇到的問題就是要把一個資料物件轉到另一個相似的資料物件裡,這個物件除了get()和set()外,幾乎沒有任何其他函式,PHP的話很簡單,不過遇到嚴謹的C#就糟糕了。

查了諸多資料,終於嘗試出一個解法,把程式碼和測試碼放在下面。

參考網頁:https://dotblogs.com.tw/JustTree/2019/01/04/140125

程式碼:

public static class DtoDataToDto

{

     /// <summary>容器物件轉換</summary>

     /// <typeparam name="T1">輸入物件格式</typeparam>

    /// <typeparam name="T2">輸出物件格式</typeparam>

    /// <param name="Data1">輸入物件資訊</param>

    /// <returns>T2</returns>

    public static T2 ObjectDataChange<T1, T2>(T1 Data1)

    {

        string strjsonData = JsonConvert.SerializeObject(Data1);

        var returnData = JsonConvert.DeserializeObject<T2>(strjsonData);

        return returnData;

    }

}


測試碼:

    class TestDemo1

    {

        public int item1 = 1;

        public string item2 = "2";

        private int item3 = 3;

        private string item4 = "4";

        public int item5 { get { return item3; } }

        public string item6 { get { return item4; } }

    }


    class TestDemo2

    {

        public int item1;

        public string item2;

        private int item3;

        private string item4;

        public int item5 { get { return item3; } }

        public string item6 { get { return item4; } }

    }


    [TestClass]

    public class DtoDataToDtoTest

    {

        [TestMethod]

        public void ObjectChangeDataTest()

        {

            TestDemo1 testDemo1 = new TestDemo1();

            TestDemo2 testDemo2 = DtoDataToDto.ObjectDataChange<TestDemo1, TestDemo2>(testDemo1);

            Assert.AreEqual(testDemo1.item1 , testDemo2.item1);

            Assert.AreEqual(testDemo1.item2, testDemo2.item2);

            Assert.AreNotEqual(testDemo1.item5, testDemo2.item5);

            Assert.AreNotEqual(testDemo1.item6, testDemo2.item6);

            Assert.AreEqual(testDemo2.item5 , 0);

            Assert.IsNull(testDemo2.item6);

        }

    }