2011年11月29日 星期二

[asp.net] 永久登入,延長(自訂)表單驗證(Forms Authentication)保存時間

有些網站會提供記錄使用者登入密碼二週或永久
如pchome的 '記住我的密碼' 、 yahoo的 '保持我的登入狀態'

若使用Login控制項時,可以在Login控制項的LoggedIn事件裡面加入下面的程式碼:

// 使用Login控制項,在成功登入之後會自動幫我們建立驗證的cookie
// 所以我們必須拿出來重新修改,改成我們希望延長的時間
HttpCookie cookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];

// 從cookie解碼還原票證
FormsAuthenticationTicket oldTicket = FormsAuthentication.Decrypt(cookie.Value);

// 建立新的票證 註:DateTime.Now.AddYears(1)為票證到期日,也就是希望延長的期限
FormsAuthenticationTicket newTicket = new FormsAuthenticationTicket(oldTicket.Version,
oldTicket.Name, DateTime.Now, DateTime.Now.AddYears(1), oldTicket.IsPersistent, oldTicket.UserData, FormsAuthentication.FormsCookiePath);

// 使用新的票證來建立新的驗證cookie
string cookiestr = FormsAuthentication.Encrypt(newTicket);
HttpCookie newCookie = new HttpCookie(FormsAuthentication.FormsCookieName, cookiestr);
newCookie.Expires = newTicket.Expiration;
newCookie.Path = FormsAuthentication.FormsCookiePath;

// 最後將新的驗證cookie重新寫回給user
Response.Cookies.Add(newCookie);

-----完成-----

2011年11月24日 星期四

submit特定元素的資料

有時候因為某些不可抗拒的因素,而只能將某些html元素寫在某個form當中

例子如下:

<form id="form1" method="post" action="post_target.html">
<input id="txtName" type="text" name="Name">
<input id="txtTel" type="text" name="Tel">
<input id="txtAddr" type="text" name="Address">
<input id="btnSend" type="submit" value="送出">
</form>
此時一按下送出,就會將整個form1的資料送出去

如果希望只送出Name欄位的資料出去該怎麼做呢?
以下為了程式碼的精簡,使用了jQuery來處理dom物件,改寫後的code如下
<form id="form1"> // 將 method="post" action="post_target.html"拿掉
<input id="txtName" type="text" name="Name">
<input id="txtTel" type="text" name="Tel">
<input id="txtAddr" type="text" name="Address">
<input id="btnSend" type="button" value="送出" onclick="doPost();" />
</form>

<script type="text/javascript">
function pay() {
var name= $('#txtName').val();
var form = $('<form method="post" action="post_target.html"></form>');
form.append('<input type="hidden" name="Name" value="' + name + '" />"');
$('body').append(form);
form.submit();
}
</script>

2011年11月23日 星期三

[C#] long(Int64) 與 base64 互轉

// long(Int64) 轉 base64
var buffer1 = BitConverter.GetBytes(long.MaxValue);
string str = Convert.ToBase64String(buffer1);

// base6轉long(Int64)
var buffer2 = Convert.FromBase64String(str);
long val = BitConverter.ToInt64(buffer2, 0);

2011年11月17日 星期四

LINQ動態查詢 使用(PredicateBuilder)

官網抵佳:PredicateBuilder
需使用套件: LINQKit
套件及範例下載位址:在LINQKit頁面的最下方

官網範例如下
IQueryable<SearchProducts>(params string[] keywords)
{
 var predicate = PredicateBuilder.False();
 foreach (string keyword in keywords)
 {
  string temp = keyword; // 很重要!! 一定要加
  predicate = predicate.Or (p => p.Description.Contains (temp));
 }
 return dataContext.Products.Where (predicate);
}

--------------------------------
下面是運作說明

步驟1:建立PredicateBuilder物件(我們需要使用此物建來作查詢條件的串接)
var predicate = PredicateBuilder.False();
步驟2:迴圈加入查詢條件
foreach(string keyword in keywords)
{
  string temp = keyword; // 避免參考到相同變數位址,所以需加上此行
  predicate = predicate.Or (p =< p.Description.Contains (temp));
}
步驟3:執行查詢
dataContext.Products.Where (predicate);
or 使用 dataContext.Products.Where(predicate.Compile());

-----------------完成!!------------------

接下來是運作原理的說明

當只執行
var predicate = PredicateBuilder.False();
dataContext.Products.Where (predicate.Compile());
這段描述看起來會像是 dataContext.Products.Where (src => false);

若是執行
var predicate = PredicateBuilder.False();
predicate = predicate.Or (src => src.keyword == "123");
dataContext.Products.Where (predicate.Compile());
這段描述看起來會像是 dataContext.Products.Where (src => false || src.keyword == "123");

若是執行
var predicate = PredicateBuilder.False();
predicate = predicate.Or (src => src.keyword == "123");
predicate = predicate.And(src => src.id == 5);
dataContext.Products.Where (predicate.Compile());
這段描述看起來會像是 dataContext.Products.Where (src => false || src.keyword == "123" && src.id == 5);

由此可知條件是串接起來的
因此預設選擇PredicateBuilder.False或PredicateBuilder.True就很重要了

舉個例子,如果希望找出keyword1或keyword2,兩個關鍵字只要一個成立即可的結果

範例會像這樣
var predicate = PredicateBuilder.False();
predicate = predicate.Or (src => src.keyword == "123");
predicate = predicate.Or (src => src.keyword == "456");
dataContext.Products.Where (predicate.Compile());
這段描述看起來會像是 dataContext.Products.Where (src => false || src.keyword == "123" ||src.keyword == "456"); //這是正確的結果
若預設選擇PredicateBuilder.True();
這段描述看起來會像是dataContext.Products.Where (src => true || src.keyword == "123" ||src.keyword == "456");
這樣一來查詢的結果永遠會是true,而導致錯誤了

在一個例子,如果希望找出keyword1且keyword2,兩個關鍵字都要成立的結果
範例應該像這樣
var predicate = PredicateBuilder.True();
predicate = predicate.And (src => src.keyword == "123");
predicate = predicate.And (src => src.keyword == "456");
dataContext.Products.Where (predicate.Compile());
這段描述看起來會像是 dataContext.Products.Where (src => true && src.keyword == "123" && src.keyword == "456"); //這是正確的結果
若預設選擇PredicateBuilder.False();
這段描述看起來會像是 dataContext.Products.Where (src => false && src.keyword == "123" && src.keyword == "456");
這樣一來查詢的結果就永遠會是false,而導致錯誤了