苔蘚 / InfoPath 表單伺服器 (InfoPath 2007) 下拉清單中的性能

其他類別: InfoPath

摘要: InfoPath 2007 表單部署到 MOSS 伺服器提供廠商綁在 MOSS 的自訂清單的下拉清單. 在選擇供應商, 規則將欄位值分配給少數的如銷售代表名稱的文字欄位, 位址, 城市, 狀態, 郵編和電話. 性能很可怕. 我們注意到性能獲取更糟 (非直線的方式) 對於每個額外欄位我們更新通過這種方式. 即, 如果我們只是,更新的銷售代表名稱, 花 [x] 時間. 如果我們更新銷售代表, 位址 1, 位址 2, 城市, 狀態, 郵編, 花 10 時間更長.

解決方案: 編寫 web 服務 (可以找到的示例代碼 在這裡) 這通過一個供應商的名稱和它回返回的供應商詳細資訊. 然後, 通過這種方式指定欄位. 雖然這似乎是太慢, 有的性能沒有明顯的區別,我們分配時 1 與欄位 8 欄位. 作為額外的獎勵, 使用者可以得到"聯繫伺服器酷" 賽昂 雖然他們等待該表單以調用和消費服務結果的影響.

苔蘚: 出現異常. (HRESULT 的異常: 0x 80020009 (DISP_E_EXCEPTION))

更新: 我們永遠不會再次確定這一問題,它從來沒有表面的根本原因.

我們注意到在開發網站的實施過程中,突然間, 兩個使用者不能訪問網站集合. 這些帳戶可以到主網站進行身份驗證, 但當試圖訪問特定網站集, 他們只是得到一個空白的螢幕. 不顯示錯誤訊息, 只是一個白色的空白頁.

我們網站集合管理員身份登錄,並嘗試添加這些使用者之一作為網站管理員,這一次, 後按下"確定", 我們得到此消息:

出現異常. (HRESULT 的異常: 0x 80020009 (DISP_E_EXCEPTION))

我們花了一些時間研究這不幸的是, 沒有提出任何有用的東西. 診斷日誌中有一些消息, 但很難完全將它們與此問題相關聯.

在結束, 我們刪除網站集,並重新創建它,解決它.

如果我弄明白是什麼導致這在未來, 我將更新這個帖子.

苔蘚: 反覆運算通過自訂清單,並將篩選後的資料返回到 InfoPath

業務應用場景:

提供一種方法,使使用者能夠快速輸入準確的採購申請.

業務問題:

在用戶端與幾個幾百個供應商做生意.

供應商"類型" 具體. 這意味著一個供應商銷售電腦設備 (例如:. 戴爾) 或辦公用品 (例如:. 釘書釘).

我們如何使最終使用者創建一個有效的供應商的採購請購單選擇?

業務解決方案:

在"類型"通過系統中區分的供應商.

使使用者能夠選擇"類型" 產品的然後提供一組篩選合適的供應商.

技術解決方案:

使使用者能夠輸入線上購買請購單已設計 InfoPath 表單.

兩個 InfoPath 挑選清單控制供應商選擇. 第一次, 使用者選擇"採購類型". 這就限制了第二次的挑選清單包含只有賣那採購類型的供應商. 這是一個經典的級聯下拉.

與供應商的屬性,如名稱的自訂列的 MOSS 自訂清單中存儲供應商, 位址和特別是"類型".

要消耗,InfoPath 用戶端的 web 服務實現逐一查看自訂的供應商清單, 返回僅匹配提供的"類型"的供應商.

調用 web 服務通過 InfoPath 表單.

吸取的經驗教訓:

  • 第一次, 似乎有必要走這條路. 我寧願做完全屬於 InfoPath 的篩選並不創建任何的 web 服務功能. 不過, 表單伺服器不提供所需的過濾功能. 我們可以把放到一個規則"類型" 挑選清單中該表單以某種重新打開該供應商查詢, 但我們不能讓它正常工作. 因此, 有必要實現的 web 服務.
  • 這是一個經典"級聯挑選清單" 在 InfoPath 中的問題形成伺服器世界並有很好的例子很多外面解釋了如何解決此問題.
  • 供應商清單中的列的為空值不會返回一個空字串時這樣引用: initItem["供應商名稱"]. 相反, 它將返回一個空值.

一些其他注意事項:

  • 返回一個[] 供應商的因為我已經返回陣列有些困難. InfoPath 抱怨說它並沒有時間或傾向為爭奪它. 這, 答案是肯定的, 人工限制放的供應商總數. 它還迫使我實施修剪() 方法在陣列上的因為我痛恨的返回回 100 的空供應商. InfoPath 不在乎, 但它困擾著我. (再次, 這是比 InfoPath 爭奪陣列清單更容易).
  • 我實現 GetSpecificVendorByName() 功能以及, 這可能是有教育意義.

代碼:

使用 系統;
使用 System.Web;
使用 System.Web.Services;
使用 System.Web.Services.Protocols;
使用 Microsoft.SharePoint;
使用 System.Configuration;

/// <摘要>
///
供應商服務: 提供了相關的供應商服務,今天由 infopath 用戶端表單.
///
/// 歷史:
/// ——–
/// 07/24/07: 初始編碼, Paul J. 加文的 Conchango.
///
/// </摘要>
[Web 服務(Namespace = "HTTP://www.conchango.com/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
公眾 VendorService : System.Web.Services.Web 服務
{

/// <摘要>
/// 表示由 MSUSA 維護的自訂 sharepoint 清單中的供應商.
/// </摘要>
公眾 供應商
{
公眾 供應商() { }

公眾 供應商(SPItem initItem)
{
如果 (! (initItem["供應商名稱"] == 則為 null)) VendorName = initItem["供應商名稱"].ToString();
如果 (! (initItem["位址 1"] == 則為 null)) VendorAddress1 = initItem["位址 1"].ToString();
如果 (! (initItem["位址 2"] == 則為 null)) VendorAddress2 = initItem["位址 2"].ToString();
如果 (! (initItem["城市"] == 則為 null)) VendorCity = initItem["城市"].ToString();
如果 (! (initItem["VendorPhone"] == 則為 null)) VendorPhone = initItem["VendorPhone"].ToString();
如果 (! (initItem["PurchaseType"] == 則為 null)) VendorType = initItem["PurchaseType"].ToString();
如果 (! (initItem["狀態"] == 則為 null)) VendorState = initItem["狀態"].ToString();
如果 (! (initItem["郵編"] == 則為 null)) VendorZip = initItem["郵編"].ToString();
如果 (!(initItem["傳真機器"] == 則為 null)) VendorFax = initItem["傳真機器"].ToString();
如果 (!(initItem["SalesRepName"] == 則為 null)) VendorSalesRepName = initItem["SalesRepName"].ToString();

VendorItemId = initItem.ID; // 保持通過 MOSS 的唯一 ID.
}

公眾 int VendorItemId;
公眾 字串 VendorName;
公眾 字串 VendorAddress1;
公眾 字串 VendorAddress2;
公眾 字串 VendorCity;
公眾 字串 VendorState;
公眾 字串 VendorZip;
公眾 字串 VendorPhone;
公眾 字串 VendorType;
公眾 字串 VendorSalesRepName;
公眾 字串 VendorFax;
}

公眾 VendorService () {

//取消注釋以下行如果使用設計的部件
//InitializeComponent();
}

私人 供應商[] GenerateTestVendors()
{
供應商[] resultList;
resultList = 新增功能 供應商[100];

供應商 v;
v = 新增功能 供應商();
v.VendorAddress1 = "v1_address1";
v.VendorAddress2 = "v1_address2";
v.VendorCity = "v1_city";
v.VendorName = "v1_vendorname";
v.VendorPhone = "v1_vendorphone";
v.VendorState = "v1_st";
v.VendorType = "v1_type";
v.VendorZip = "v1_zip";

resultList[0] v =;

v = 新增功能 供應商();

v.VendorAddress1 = "v2_address1";
v.VendorAddress2 = "v2_address2";
v.VendorCity = "v2_city";
v.VendorName = "v2_vendorname";
v.VendorPhone = "v2_vendorphone";
v.VendorState = "v2_st";
v.VendorType = "v2_type";
v.VendorZip = "v2_zip";

resultList[1] v =;

v = 新增功能 供應商();
v.VendorAddress1 = "v3_address1";
v.VendorAddress2 = "v3_address2";
v.VendorCity = "v3_city";
v.VendorName = "v3_vendorname";
v.VendorPhone = "v3_vendorphone";
v.VendorState = "v3_st";
v.VendorType = "v3_type";
v.VendorZip = "v3_zip";

resultList[2] v =;

返回 resultList;

}

[WebMethod]
公眾 供應商 GetSpecificVendorById(int vendorId)
{
字串 SpVendorSiteName; // 主機供應商自訂清單的實際的 MOSS 網站名稱.
字串 SpVendorListName; // 實際的苔蘚清單包含供應商的名稱.

SpVendorSiteName = ConfigurationSettings.AppSettings["VendorListHostingSite"].ToString();
SpVendorListName = ConfigurationSettings.AppSettings["VendorList"].ToString();

使用 (SPSite 網站 = 新增功能 SPSite(SpVendorSiteName))
{

使用 (SPWeb web = 網站。OpenWeb())
{

SPList currentList = web。清單[SpVendorListName];

SPItem specificItem = currentList.Items[vendorId];

返回 新增功能 供應商(specificItem);

} // 使用 spweb web = site.openweb()
} // 使用 spsite 網站 = 新 spsite("HTTP://本地主機/瑞穗")

}

[WebMethod]
// 假設供應商名稱是唯一, 從業務的角度
公眾 供應商 GetSpecificVendorByVendorName(字串 vendorName)
{
字串 SpVendorSiteName; // 主機供應商自訂清單的實際的 MOSS 網站名稱.
字串 SpVendorListName; // 實際的苔蘚清單包含供應商的名稱.

SpVendorSiteName = ConfigurationSettings.AppSettings["VendorListHostingSite"].ToString();
SpVendorListName = ConfigurationSettings.AppSettings["VendorList"].ToString();

使用 (SPSite 網站 = 新增功能 SPSite(SpVendorSiteName))
{
使用 (SPWeb web = 網站。OpenWeb())
{

SPList currentList = web。清單[SpVendorListName];

foreach (SPItem vendorItem 在中 currentList.Items)
{
如果 (vendorItem["供應商名稱"] == 則為 null) 繼續;

如果 (vendorItem["供應商名稱"].ToString().合計(vendorName))
返回 新增功能 供應商(vendorItem);
}

供應商 v = 新增功能 供應商();
v.VendorPhone = "找不到: " + vendorName;

返回 v;

返回 則為 null;

} // 使用 spweb web = site.openweb()
} // 使用 spsite 網站 = 新 spsite("HTTP://本地主機/瑞穗")

} // 方法

[WebMethod]
公眾 供應商[] GetVendorsOfType (字串 式防塵)
{

字串 SpVendorSiteName; // 承載 t 的實際的 MOSS 網站名稱
他供應商自訂清單.
字串 SpVendorListName; // 實際的苔蘚清單包含供應商的名稱.

SpVendorSiteName = ConfigurationSettings.AppSettings["VendorListHostingSite"].ToString();
SpVendorListName = ConfigurationSettings.AppSettings["VendorList"].ToString();

供應商[] resultList;
int vendorIndex = 0;
resultList = 新增功能 供應商[1000];

// 初始化預設友好消息清單.
供應商 v = 新增功能 供應商();
v.VendorName = 選擇供應商類型來填充該清單。";
resultList[0] v =;

// 轉換為小寫為以後更容易的字串比較的篩選器.
過濾式 = filterType.ToLower();

// 如果篩選器類型傳遞的是"測試", 生成一些簡單的資料.
#地區 篩檢程式類型 ="測試"
如果 (式防塵等於。("測試"))
返回 GenerateTestVendors();
#endregion

如果 (真正的)
{
使用 (SPSite 網站 = 新增功能 SPSite(SpVendorSiteName))
{
使用 (SPWeb web = 網站。OpenWeb())
{

v = 則為 null;

SPList currentList = web。清單[SpVendorListName];

// 逐一查看供應商清單中的所有項.
foreach (SPItem vendorItem 在中 currentList.Items)
{

字串 lowerVendorType;

lowerVendorType = vendorItem["PurchaseType"].ToString().String.tolower();
lowerVendorType = lowerVendorType.Substring(3);

如果 (lowerVendorType 等於。(式防塵))
{
resultList[vendorIndex ] = 新增功能 供應商(vendorItem);
}
} // 通過在清單中的所有供應商進行反覆運算


返回 TrimVendorArray(vendorIndex, resultList);
// 返回 resultList;

} // 使用 spweb web = site.openweb()
} // 使用 spsite 網站 = 新 spsite("HTTP://本地主機/瑞穗")

} // 如果為 true,

返回 則為 null;
}

私人 供應商[] TrimVendorArray(int newsize, 供應商[] originalVendorArray)
{
供應商[] trimmedArray;

如果 (newsize = = 0) newsize = 1;
trimmedArray = 新增功能 供應商[newsize];

int currentCounter = 0;

對於 (currentCounter = 0; currentCounter < newsize; currentCounter )
{
trimmedArray[currentCounter] originalVendorArray =[currentCounter];
}

返回 trimmedArray;

}
}

苔蘚: InfoPath 調試的觀察

InfoPath 表單伺服器錯誤消息是誤導.

在 InfoPath 表單的開發過程中, 我會張貼到 MOSS 伺服器和訪問表單. 該表單將開始載入,然後生成一個具誤導性的錯誤訊息,我指向 windows 事件日誌中的詳細資訊. 事實上, 沒有消息被寫入 windows 事件日誌. 而是, 該消息被發送到 MOSS ascii 診斷日誌. 您可以跟蹤,通過中央服務管理.

您需要快速的你的雙腳. MOSS 喜歡寫到日誌檔, 經常和過程. 這可以被修剪,但預設日誌寫入的行為是"一切都盡可能快地".

苔蘚: 更新自訂清單

有許多很好的例子的更新通過 SDK 的自訂清單. 這裡是另一個.

業務問題: InfoPath 表單而設計使使用者能夠輸入線上購買請購單. 大埔徵用的數位應該是傳統序列基於整數值和自動計算.

業務解決方案: 創建一個包含兩列的自訂 MOSS 清單: "ControlField" 和"ControlValue". 值列包含下一個採購請購單編號. 請注意該泛型"控制" 對於未來控制欄位,可根據需要提供了命名約定.

技術解決方案: 創建的 InfoPath 用戶端存取的 web 服務. 在 web 服務返回返回下一個採購請購單編號和更新清單中的值.

吸取的經驗教訓:

  • 將此 web 服務作為資料來源添加到 InfoPath 表單時, 我發現有必要將它轉換為 udc 並將其存儲到資料連線庫.
  • 此外發現它有必要啟用跨域腳本通過中央服務管理 // 應用程式管理 // 表單伺服器配置.
  • 第一次表單試圖訪問的 web 服務, 它需要一段時間,有時, 它將超時時間. 我擺弄設置在表單的伺服器配置中,展開超時設置,這似乎説明.

代碼:

使用 系統;
使用 System.Web;
使用 System.Web.Services;
使用 System.Web.Services.Protocols;
使用 Microsoft.SharePoint;
使用 System.Configuration;

[Web 服務(Namespace = "HTTP://www.conchango.com/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
公眾 PoService : System.Web.Services.Web 服務
{
公眾 PoService () {

//取消注釋以下行如果使用設計的部件
//InitializeComponent();
}

/// <摘要>
/// 從 sharepoint po 號碼控制清單獲得下一個 PO 編號.
/// 該清單中的增量 PO 編號.
/// </摘要>
/// <返回></返回>
[WebMethod]
公眾 字串 GetNextPoNumber()
{
字串 SpPoControlSiteName; // 實際的 MOSS 網站承載的大埔控制清單名稱.
字串 SpPoControlListName; // 包含寶控制項的實際苔蘚清單的名稱.

SpPoControlSiteName = ConfigurationSettings.AppSettings["PoControlListHostingSite"].ToString();
SpPoControlListName = ConfigurationSettings.AppSettings["PoControlList"].ToString();

字串 nextPoReqNumber = "xyzzy";

使用 (SPSite 網站 = 新增功能 SPSite(SpPoControlSiteName))
{
使用 (SPWeb web = 網站。OpenWeb())
{

SPList currentList = web。清單[SpPoControlListName];

foreach (SPItem controlItem 在中 currentList.Items)
{

如果 (((字串)controlItem["ControlField"]).合計("NextPoNumber"))
{
nextPoReqNumber = (字串)controlItem["ControlValue"];

int int_nextPoReqNumber;
int_nextPoReqNumber = 轉換.ToInt32(nextPoReqNumber);

int_nextPoReqNumber ;

controlItem["ControlValue"] int_nextPoReqNumber =;
controlItem.Update();
}

} // 定位, 讀取和更新採購訂單編號清單中.


} // 使用 spweb web = site.openweb()
} // 使用 spsite 網站 = 新 spsite("HTTP://本地主機/瑞穗")

返回 nextPoReqNumber;

}
}