C# 網頁開發小技巧

一些在開發網頁中會用到的小技巧,幫助改善開發的效率

列出目前幾個自己常用的:

※善用using
using完的物件會自動Close與Dispose,所以建議需要Dispose的物件都可以使用using
像是SqlConnection, SqlCommand, SqlDataReader...

using (SqlConnection conn = new SqlConnection("xxx"))
{
    conn.Open();
}   // 結束時不需要Close跟Dispose

※用@來設定多行的SQL語法
雖然我個人比較推薦把SQL語法都寫在查詢產生器中(減少程式碼複雜度,還能驗證)
不過某些時候還是必須要把SQL寫在code中
從Java轉過來的人可能會這樣寫

string sql = "SELECT field1, field2" +
             "FROM table1" +
             "WHERE field3 = @Param1";

其實在ASP.NET不需要這麼麻煩每一行要串接,在字串前加上@就能做到跨行:

string sql = @"SELECT field1, field2
               FROM table1
               WHERE field3 = @Param1";

※用TryParse轉換可能會出錯的字串
幾乎所有的基本型態都有TryParse方法
TryParse的特點是如果字串轉換失敗,不會拋出Exception
如果出錯後,變數會變成初始值0,如果希望同時給予不同值,可以這樣寫:

int i;
if (!int.TryParse("", out i))
{
    i = 100;
}

※用??代替麻煩的條件判斷

string str;
if (WebConfigurationManager.AppSettings["xx"] != null)
{
    str = WebConfigurationManager.AppSettings["xx"];
}
else
{
    str = "defaultValue";
}
 
string str = WebConfigurationManager.AppSettings["xx"] ?? "defaultValue";   // 與上面同義
 
string str = val1 ?? val2 ?? val3 ?? val4;   // 依序判斷val1, val2, val3, val4是否有值,有值即設定值

※GridView要如何做到按下一行自動選取該行(select row)

在GridView的RowDataBound輸入以下code:

protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
    if (e.Row.RowType == DataControlRowType.DataRow)
    {
        e.Row.Attributes["onclick"] = ClientScript.GetPostBackClientHyperlink(this.GridView1, "Select$" + e.Row.RowIndex);
        e.Row.Style.Add(HtmlTextWriterStyle.Cursor, "pointer");   // 滑鼠移上去時,變成點選樣式
    }
}

但輸入完後會出現以下訊息

gridview_row解決方法:覆寫該頁Render,註冊其事件驗證

protected override void Render(HtmlTextWriter writer)
{
    for (int i = 0; i < this.GridView1.Rows.Count; i++)
    {
        Page.ClientScript.RegisterForEventValidation(this.GridView1.UniqueID, "Select$" + i.ToString());
    }
    base.Render(writer);
}

※在刪除按鈕點下去前先跳出一個確認視窗,選擇確定才PostBack
Button的OnClientClick輸入
return confirm("Are you sure?");

※如何顯示MessageBox
ASP.NET沒這東西,你只能動態註冊JS呼叫alert

ScriptManager.RegisterStartupScript(this, this.GetType(), "alert", "alert('" + Message + "');", true);

※要怎麼做到按下按鈕後跳出新視窗(open new window),在新視窗輸入內容(Ex.帳號密碼)後回傳(return value)的效果
純ASP.NET無法做到,只能使用JS,請搜尋關鍵字showModalDialog
以下方法不是最好的方法...如果有更好的作法請跟我說

假設要從A頁面呼叫B頁面,輸入完資料再回傳A頁面
在A.aspx寫入此JS (要直接寫或用動態註冊皆可)

var returnValue = window.showModalDialog(url, "", "dialogWidth:300px;dialogHeight:300px;");   // 還有很多參數可用
if (returnValue != undefined) {
    __doPostBack(target, returnValue);   // target自訂
}

在B.aspx寫入此JS

function selectBack(valueString) {
    window.returnValue = valueString;
    window.close();
}

在B.aspx的控制項上呼叫此方法
javascript:selectBack('" + encodeKeyString + "')
最後在A.aspx.cs接收此PostBack參數

※網頁原始檔部份有內建的排版(format)工具嗎?
網頁全選後按右鍵,選擇"格式化選取範圍"

※如何避免SQL衝突 (兩人修改同一筆資料)
假設有個資料表是這樣(id是Primary Key)
id name
1  小明
2  小華
如果資料庫要修改欄位內容,一般SQL會寫
Update name = @Name Where id = @id
但如果同時有兩個人要修改小明的name,就會變成"後進先寫入"
也就是後面寫入的資料會蓋過前面寫入的資料
解決法是把SQL改寫成這樣
Update name = @Name Where id = @id and name = @origin_name
這樣當第一個人把"小明"修改成"小明1"之後
第二個人就無法找到name=小明的資料,所以不會覆蓋到第一個人的修改結果

※DropDownList要怎麼根據Text或Value改變他的選取值

DropDownList1.SelectedIndex = DropDownList1.Items.IndexOf(DropDownList1.Items.FindByText("text"));
DropDownList1.SelectedValue = "XXX";   // 如果只要根據Value選擇,直接這樣寫就好

※DateTime要怎麼重新設定時間,且不使用new
沒有辦法,請直接用new給予新值

DateTime dt = new DateTime(2012, 12, 12);
dt = new DateTime(2011, 11, 11);

DateTime是struct,所以直接取代掉就好了
struct是value type,所以並不會浪費記憶體

※如何讓DateTime指定為該月最後一天?
1. DateTime.DaysInMonth(year, month);
2. new DateTime(year, month, 1).AddMonths(1).AddDays(-1);

※SQL要怎麼把很多筆資料(multi row)變成單行字串(single string)?

比方說今天有資料如下
ID Name
1 Name1
1 Name2
2 Name1
2 Name3
2 Name5
希望轉成以下的欄位
ID Name
1 Name1,Name2
2 Name1,Name3,Name5

如果是MSSQL有個偷吃步的方法,就是使用FOR XML PATH('')語法
將取得的欄位轉變成一個用空白tag包覆的XML內容

SELECT A.ID,
       (
          SELECT B.Name + ','
          FROM [TableB] AS B
          WHERE B.ID = A.ID
          FOR XML PATH('')
       ) AS Name
FROM [TableA] As A

※GridView某欄位在設定Visible=false後,PostBack之後無法取得該欄位的值
因為這個欄位在一開始產生網頁的時候就不會寫進去,所以自然無法取得不存在的資料
解決法
HeaderStyle跟ItemStyle設定CSS,CSS內容為display:none;

※字串直接串接比較好還是用string.Format串接比較好?
用string.Format串接比較快,因為其內部是使用StringBuilder實作

※decimal跟double的差別?
Decimal 不是浮點數資料型別。Decimal 結構會保存二進位整數值,加上正負號位元和整數縮放比例,指定值的哪一部分是小數部分。
簡單的說,double因為是用byte去儲存小數,所以每次都會有誤差,而decimal是用十進位去存小數,所以不會有誤差
如果要儲存金額等這種不允許誤差的數值,就要用decimal

※那為什麼List可以直接放基本型別?

List<int> list = new List<int>();   // 像這樣

因為C#會自動幫你做轉換

※int.Parse跟Convert.ToInt32有什麼差別?
1. int.Parse只能傳入string,Convert.ToInt32可以讀取各種型態
2. 當傳入參數為null時,int.Parse會拋出exception,Convert.ToInt32會回傳0

 

資料參考來源:http://catchtest.pixnet.net/blog/post/28219055-asp.net-%E4%BD%BF%E7%94%A8%E7%AD%86%E8%A8%98