2011年9月29日 星期四

[jQuery] 取得連結內容,將其放到容器中。

jQuery 取得連結內容後,將內容放到容器中。

網頁連結
// jQuery
$(document).ready(function () {
    $(".link").click(function () {
        $("div#container").empty().load($(this).attr('href'));
        return false;
    });
});



2011年7月25日 星期一

[SQL Server] 筆記 "限制的使用者"

最近從人家那拿來的 DB 備份,還原後總是會在 db 後面加上(限制的使用者)
運作上感覺是沒什麼問題,可是總覺得那字樣很礙眼,哈哈。
Google 到的方法,筆記一下。
ALTER DATABASE [YourDBName]
SET MULTI_USER WITH ROLLBACK IMMEDIATE;
就這樣...



2010年11月15日 星期一

2010年9月15日 星期三

[筆記]不用第三個變數,交換兩個數值的方法

今天翻到一段程式碼,想不起來這是在做些什麼?
後來終於找到這段程式是在做交換兩個數值,
而且,不宣告第三個變數!
其實好像也不是什麼大不了的東西,
不過還是筆記一下,人老了越來越會忘東忘西...

不宣告第三個變數暫存的方式
int a = 10;
int b = 5;

a ^= b;
b ^= a;
a ^= b;

結果就會從 a = 10, b = 5,
變成 a = 5, b = 10

宣告第三個變數暫存的方式
int a = 10;
int b = 5;
int temp;

temp = a;
a = b;
b = temp;

一樣的結果,不一樣的寫法,
簡單來說前者就是拿時間換空間,
後者就是拿空間換時間。


2010年8月2日 星期一

連結的伺服器(Linked Server)筆記

之前佈署測試環境,發生了一連串關於"連結的伺服器(Linked Server)"的問題,
第一個問題:
訊息 7399,層級 16,狀態 1,行 1
連結伺服器 "db_host" 的 OLE DB 提供者 "SQLNCLI10" 報告了錯誤。提供者並未給予任何關於錯誤的資訊。
訊息 7312,層級 16,狀態 1,行 1
不能使用連結伺服器 "db_host" 的 OLE DB 提供者 "SQLNCLI10" 的結構描述或目錄。提供了四部分的名稱,但提供者並未公開必要的介面,以使用目錄或結構描述。

這錯誤訊息的關鍵字不難看出是"提供者"。
點開"提供者"後,滑鼠右鍵點"SQLNCLI10"選屬性即可開啟"提供者選項"


因此,我們看了一下"提供者選項",發現裡面所有選項都被選取了...
這時候我們拜一下 Google 大神,找到取消"限層級零"與"不允許特定存取"可以解決我們的問題。


對於這些選項說明可以看一下:連結的伺服器屬性(提供者選項頁面)

感覺還會有問題...
果然,隔天又發現有 error,經過檢查發現,又是 Linked Server 的問題。
這次出現什麼碗糕哩!?
連結伺服器 "db_host" 的 OLE DB 提供者 "SQLNCLI10" 傳回訊息 "Multiple-step OLE DB operation generated errors. Check each OLE DB status value, if available. No work was done."。
訊息 7306,層級 16,狀態 2,行 1
無法從連結伺服器 "db_host" 的 OLE DB 提供者 "SQLNCLI10" 開啟資料表 ""db_name"."dbo"."table_name""。提供者不支援在這個資料來源上的索引掃描。

這訊息的關鍵字"提供者"、"索引"
看了就覺得這和上面的問題有點點關係,因為"索引為存取路徑"也是被勾選的嘛...
將它取消以後,系統便正常了...

目前尚有一個問題未解決,那就是預存程序更新 Linked Server 裡的 Database,
如果沒有加 Transaction,一切正常,加了以後就出現了:
連結伺服器 "db_host" 的 OLE DB 提供者 "SQLNCLI10" 傳回訊息 "異動已經以暗示或者明確的方式認可或中止了"。
訊息 7391,層級 16,狀態 2,行 5
無法執行作業,因為連結伺服器 "db_host" 的 OLE DB 提供者 "SQLNCLI10" 無法開始分散式交易。
這問題比較頭痛一點,因為照著 Google 找到的一些方法,仍然是沒能解決...
解決以後再來更新這篇文章吧...

最後一個問題終於解決,
基本上就是將兩台機器的 MSDTC 開啟,並且做一些設定,
首先進入"元件服務"


接著找到"我的電腦",然後右鍵點擊選取"內容"


選取 MSDTC 頁籤,並且點選"安全性設定"


將裡面的設定設定成下面畫面


在 Windows Server 2003 SP2 不需要特地去改機碼,
如果你是 SP1 的版本,或是用 Windows XP 測試的話,
請檢查下面這機碼是否存在,其值是否為1
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSDTC]
"TurnOffRpcSecurity"=dword:00000001

點此下載檔案

然後,最重要的一個步驟就是,將這兩台機器都重新開機

事實上,在 Microsoft 技術支援 裡面就有說明解法,
只是那時候心急,忽略了最後一個步驟:重新開機...
導致我的問題拖好久...

最後,如果只是加上 Transaction 的話,他應該還是會丟個錯誤出來 XD
連結伺服器 "db_host" 的 OLE DB 提供者 "SQLNCLI10" 傳回訊息 "異動中已經存在有徵募"。
訊息 7395,層級 16,狀態 2,行 2
無法為連結伺服器 "db_host" 的 OLE DB 提供者 "SQLNCLI10" 啟動巢狀交易。因為 XACT_ABORT 選項已設定為 OFF,所以必須要有巢狀交易。

所以我們必須要在 Transaction 之前,將 XACT_ABORT 設定為 ON,就像下面這樣
SET XACT_ABORT ON;
BEGIN DISTRIBUTED TRANSACTION
INSERT INTO [db_host].[db_name].[dbo].[table_name]
           ([id]
           ,[stringChar])
     VALUES
           (123
           ,'123456789abcdef')
COMMIT TRANSACTION

大功告成。



2010年7月27日 星期二

停止瀏覽器快取網頁 for ASP.NET MVC

瀏覽器為了加速網頁讀取,通常會採用快取,
所以使用者登出後,按下"回上一頁"幾乎都可以看到登出前瀏覽過的資料。
要避免使用者登出後使用"回上一頁"功能,最簡單的方式就是讓頁面不被快取,
在網路上找了一些方法,都是在<head></head>裡面加上:
//將網頁設為立即過期。
<meta http-equiv="Expires" content="0" />
//舊寫法,為了增加相容性。
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Cache-Control" content="no-cache" />
<meta http-equiv="Pragma-directive" content="no-cache" />
<meta http-equiv="Cache-Directive" content="no-cache" />

不過這樣做,不知道為什麼在 IIS 6 的環境上,執行 ASP.NET MVC 的 Web Application 還是可以讓使用者按下"回上一頁"...
後來發現也可以直接加在 http response headers 上,
因此,改寫了一下專案裡面 base Controller 在 Initialize 時,設定 Response 的 cache 設定,設定如下:
protected override void Initialize(RequestContext requestContext)
{
    base.Initialize(requestContext);

    requestContext.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);
    requestContext.HttpContext.Response.Cache.SetExpires(DateTime.MinValue);
    requestContext.HttpContext.Response.Cache.SetNoStore();
}
比較一下兩者狀況,
僅在頁面加上<meta...的方式:

圖上半部是程式部份,下半部是 Chrome 的開發人員工具檢視 http headers 的狀態。
瀏覽器一樣可以在登出後回上一頁。

直接在 http headers 告訴瀏覽器,不要快取:

登出後回上一頁,都會重新 request 頁面,
只要頁面需要檢查是否登入,基本上都回不去了。
問題解決...


2010年7月21日 星期三

ASP.NET MVC 之 ActionFilterAttribute

我們常常會在 Action 或是 Controller 上面看到黏了一些東西,像下面這樣:
[HttpPost]
public ActionResult Test(FormCollection testFormCollection)
{
    string Name = testFormCollection["Name"];
    string Title = testFormCollection["Title"];
    return View();
}
那個 [HttpPost] 就是我們說的 Attribute,
這可以做些什麼呢?
其實可以做的事情可多了,像是在 Action 執行前做些前處理的事情,
或是 Action 執行後做,而且很多 Action 都會用到的話,
那用 Attribute 來處理,是相當不錯的選擇。

實作上相當簡單,只要你寫個類別繼承 ActionFilterAttribute 這個抽象類別即可。

ActionFilterAttribute 這抽象類別主要有四個方法可以被覆寫:
1.OnActionExecuting
來自 IActionFilter 介面,於 Action Method 執行前,被呼叫。
2.OnActionExecuted
來自 IActionFilter 介面,於 Action Method 執行後,被呼叫。
3.OnResultExecuting
來自 IResultFilter 介面,於 Result Method 執行前,被呼叫。
4.OnResultExecuted
來自 IResultFilter 介面,於 Result Method 執行後,被呼叫。

這邊我們嘗試做一個 Form 驗證的 Attribute,
使含有不合法的字串的 Request,回應 302 Found。
using System.Collections.Specialized;
using System.Web.Mvc;

namespace MvcApplication1.Mvc.Attributes
{
    public class ValidateForm : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            base.OnActionExecuting(filterContext);
            NameValueCollection waitValidate = filterContext.HttpContext.Request.Form;
            for (int i = 0; i < waitValidate.Count; i++)
            {
                if (IsIllegalString(waitValidate[i].ToString()))
                {
                    filterContext.HttpContext.Response.Status = "302 Found";
                    break;
                }
            }
        }

        private bool IsIllegalString(string waitCheck)
        {
            string[] pattern = 
            { 
                "--", ";", "/*", "*/", "@@", "char", "nchar", "varchar", 
                "nvarchar", "alter", "begin", "cast", "create", "cursor", "declare",
                "delete", "drop", "end", "exec", "execute", "fetch", "insert", "kill",
                "open", "select", "sys", "sysobjects", "syscolumns", "table", "update"
            };
            foreach (string item in pattern)
            {
                if (waitCheck.ToLower().Contains(item))
                {
                    return true;
                }
            }
            return false;
        }
    }
}
然後我們在要處理的 Action 上,加上這個 Attribute,像下面這樣:
[HttpPost, ValidateForm]
public ActionResult About()
{
    return View();
}
接著找個 View 建立一個 Form 將資料 Post 給 About 這個 Action,像下面這樣:


執行畫面:


送出後,用 Firebug 查看,發現 Http Status 被改了!
如果輸入字串中並沒有任何 pattern 裡面的字串的話則會收到 200 OK


這樣就完成任務啦,Attribute 有很多應用面,比方說使用者的操作紀錄,
或是權限驗證與檢查等等,都是可以發揮的地方。
此範例可以將 Http Status 設為 302 Found 那邊換成你想要處理的邏輯。