2007年12月29日 星期六

用戶端瀏覽器無法在登入至已啟用ADFS Web Agent的SPS2003後,就順利導向到SharePoint Portal Server 2003首頁。

【問題】
  在使用者利用新的瀏覽視窗,第一次登入到已安裝ADFS Web Agent的SPS2003 Web Front時,必須輸入完整的URL,如https://adfsweb/default.aspx,瀏覽器才能夠導向至SPS2003的首頁。
  若只輸入網站位置,如https://adfsweb/,瀏覽器就會顯示系統回應之訊息"Cannot complete this action. Please try again.";
  而此時在瀏覽器的網址列上,所顯示之網址為https://adfsweb/_vti_bin/owsser.dll,而不是https://adfsweb/default.aspx,或是https://adfsweb/。
  使用者需要在瀏覽器上重新輸入網站位置,方能重新顯示SPS2003的頁面。顯示之畫面如下:

【原因】
  ADFS Web Agent中的ADFS ISAPI Filter之執行順位低於stsfltr Filter。

【處理方式】
  將ADFS ISAPI Filter之執行順位提高。

【說明】
  我是利用微軟所提供的【ADFS Step by Step Guide】進行ADFS與SPS2003之架構建置。不過當依據Guide步驟完成後,利用用戶端瀏覽器登入SPS2003 中的ADFS Web Agent Server時,就出現了上述的狀況。
  在SPS2003安裝之後,在SPS2003 Web Server中IIS 的ISAPI Filter設定中,可以看到有一個stsfltr Filter。這個Filter是負責將外部之所有Request傳送到SPS2003網站上。如下圖所示:

  但在已安裝ADFS Web Agent之SPS2003 Web Server上面,會發現除了stsfltr Filter之外,還會有一個ADFS Filter。如下圖所示:   在登入SPS2003之前,系統會先經過ADFS進行身份識別的程序,以判斷使用者需利用那一個AD進行登入。我猜想,在驗證通過之後,ADFS Federation Server會再與ADFS Web Agent進行訊息傳遞。此時若ADFS Web Agent中的ISAPI Filter優先處理的是stsfltr這個Filter時,IIS將會把此訊息交由SPS2003處理,而SPS2003處理此訊息發生錯誤,才會出現問題中所顯示之"Cannot complete this action.Please try again."這樣的錯誤訊息。
  當我將ADFS Filter之順位調整在stsfltr上面,並套用設定之後,於用戶端重新輸入ADFS Web Agent之URL,瀏覽器就自動導向到SPS2003的首頁了。

【附註】
  上述問題的原因及處理方式是由微軟提供,而我有跟微軟反應這樣的設定應該也需要註記在ADFS Step by Step Guide之中,微軟方面已同意將此意見反應給他們的Product Team,將此內容增加到文件上。

【參考資訊】
ADFS Step by Step Guide的下載位置:
http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=062f7382-a82f-4428-9bbd-a103b9f27654






2007年12月28日 星期五

C# 3.0 - Implicitly Typed Local Variables (隱含類型區域變數)

在C# 3.0中提供一些新的語言特性;其中一種就是隱含類型區域變數。其用法是使用關鍵字var 進行區域變數的宣告,如下所示
  var age = 26;
  var username = "zhuye";
使用var關鍵字,是讓編譯器自行判斷其變數之型態;所以在CLR執行時,此變數已被編譯器指定了變數型態。以下的例子之執行結果就可以了解。
  var myInt = 0;
  var myBool = true;
  var myString = "Time, marches on...";
  var evenNumbers = new int[] { 2, 4, 6, 8 };
  var myMinivans = new List();
  var myEmployee = new Employee();

  Console.WriteLine("myInt is a:{0}", myInt.GetType().Name);
  Console.WriteLine("myBool is a:{0}", myBool.GetType().Name);
  Console.WriteLine("myString is a:{0}", myString.GetType().Name);
  Console.WriteLine("evenNumbers is a:{0}", evenNumbers.GetType().Name);
  Console.WriteLine("myMinivans is a:{0}", myMinivans.GetType().Name);
  Console.WriteLine("myEmployee is a:{0}", myEmployee.GetType().Name);


var關鍵字能夠用在以下狀況:
  1. 區域變數。隱含類型可以使用在任何的基本類型型態。包含arrays、generics、及自訂的類別型態 。
  2. for 迴圈陳述式。ex: for(var x = 1; x <>
  3. foreach 迴圈陳述式。ex: foreach(var item in list){...}
  4. using 陳述式。ex: using (var file = new StreamReader("C:\\myfile.txt")) {...}

var關鍵字使用上的限制:

  1. var關鍵字不可以使用在類別的欄位及方法之回傳值或參數上。所以以下程式碼的宣告在編譯期間就會發生錯誤:
    // 編譯錯誤!var關鍵字不能被使用在宣告類別資料
    private var myInt = 10;

    // 編譯錯誤!var關鍵字不能被使用在方法之回傳值或是方法的參數
    public var MyMethod(var x, var y){}
  2. 宣告隱含類型變數時,必須同時指定變數值,且不可以指定初始值為null;但是可以在指定初始值後將物件值設定為null。
    // 編譯錯誤!利用var關鍵字宣告之變數必須指定變數值
    var myData;

    // 編譯錯誤!利用var關鍵字宣告之變數必須於宣告時同時指定變數值
    var myInt;
    myInt = 0;

    // 編譯錯誤!利用var關鍵字宣告之變數不可指定為null
    var myObj = null;

    // OK!
    var myCar = new SportsCar();
    myCar = null;

隱含類型變數也可以宣告成陣列型態。但是要注意的部份是變數陣列在宣告時,陣列值必須同時被初始化,且陣列內成員的型態中不可以混合。

  var a = new[] { 1, 2, 3, 4000 };  // 變數a 被視為一個整數型別陣列(int[])
  
   var b = new[] { 1, 1.5, 2, 2.5 };  // 變數b 被視為一個雙精準度型別陣列(double[])

  var c = new[] { "we", null, "are", null, "family" };  // 變數c 被視為一個字串型別陣列(string[])

  var myCars = new[] { new SportsCar(), new SportsCar()}; // 變數myCars 被視為一個SportsCar型別陣列

  var d = new[] { 1, "one", 2, "two" }; // 編譯錯誤!利用var關鍵字宣告的陣列成員,其值不可以有混合型態