2012-11-26 88 views
6

由於我們需要使用LDAPS連接到LDAP服務器,因此我們必須使用LdapConnection而不是DirectoryEntry。LdapConnection SearchRequest爲「超出大小限制」拋出異常

這裏是源代碼:

 SearchResponse response; 
     using (LdapConnection con = new LdapConnection(new LdapDirectoryIdentifier(Host, Port))) 
     { 
      if (IsSSL) 
      { 
       con.SessionOptions.SecureSocketLayer = true; 
       con.SessionOptions.VerifyServerCertificate = 
        (connection, certificate) 
        => true; 
      } 
      con.Credential = new NetworkCredential(_username, _password); 
      con.AuthType = AuthType.Basic; 
      con.Bind(); 

      if (logMessage != null) 
       logMessage("Connected to LDAP"); 

      string sFilter = String.Format(
       "(&(objectcategory=person)(objectclass=user){0}(!(userAccountControl:1.2.840.113556.1.4.803:=2)))", 
       filter 
       ); 

      SearchRequest request = new SearchRequest("OU=Corp,DC=mydc,DC=com", sFilter, SearchScope.Subtree); 
      request.Attributes.Add(Resources.objectguid); 
      request.Attributes.Add(Resources.givenname); 
      request.Attributes.Add(Resources.sn); 
      request.Attributes.Add(Resources.initials); 
      request.Attributes.Add(Resources.samaccountname); 
      request.Attributes.Add(Resources.userprincipalname); 
      request.Attributes.Add(Resources.mail); 
      request.Attributes.Add(Resources.objectsid); 
      request.Attributes.Add(Resources.department); 
      request.Attributes.Add(Resources.company); 
      request.SizeLimit = 10; 

      response = (SearchResponse) con.SendRequest(request); 
     } 

在源代碼的執行(我們已經驗證憑據,主機,端口等 - 使用外部第三方軟件),我們得到以下異常:

超過大小限制

描述:執行當前Web請求期間發生未處理的異常。請查看堆棧跟蹤以獲取有關該錯誤的更多信息以及源代碼的位置。

異常詳細信息: System.DirectoryServices.Protocols.DirectoryOperationException:大小限制超出

源錯誤:

response = (SearchResponse) con.SendRequest(request); 
[DirectoryOperationException: The size limit was exceeded] 
    System.DirectoryServices.Protocols.LdapConnection.ConstructResponse(Int32 

messageId, LdapOperation operation, ResultAll resultType, TimeSpan requestTimeOut, Boolean exceptionOnTimeOut) +2385 System.DirectoryServices.Protocols.LdapConnection.SendRequest(DirectoryRequest request, TimeSpan requestTimeout) +499 System.DirectoryServices.Protocols.LdapConnection.SendRequest(DirectoryRequest request) +50 UserSearchProvider.ADUserSearchProvider.QueryStore(UserSearchCriteriaCollection criterias, Action 1 logMessage) in c:\Users\stemarie\Documents\Visual Studio 2012\Projects\Idealink.Modules\UserSearchProvider\UserSearchProvider\ADUserSearchProvider.cs:298 UserSearchProvider.UserSearchProvider.QueryAndSort(UserSearchCriteriaCollection criterias, Action 1 logMessage) in c:\Users\stemarie\Documents\Visual Studio 2012\Projects\Idealink.Modules\UserSearchProvider\UserSearchProvider\UserSearchProvider.cs:77 UserSearchProvider.UserSearchProvider.Search(UserSearchCriteriaCollection criterias, Action 1 logMessage) in c:\Users\stemarie\Documents\Visual Studio 2012\Projects\Idealink.Modules\UserSearchProvider\UserSearchProvider\UserSearchProvider.cs:33 UserSearchProvider.UserSearchService.Search(UserSearchCriteriaCollection criterias, Action 1 logMessage) in c:\Users\stemarie\Documents\Visual Studio 2012\Projects\Idealink.Modules\UserSearchProvider\UserSearchProvider\UserSearchService.cs:44 UserSearchProviderTest._Default.Page_Load(Object sender, EventArgs e) in c:\Users\stemarie\Documents\Visual Studio 2012\Projects\Idealink.Modules\UserSearchProvider\UserSearchProviderTest\Default.aspx.cs:28

,混淆我的部分是,我們做指定最大大小限制,我們不希望超過100個條目 - 我們想限制它。但是,即使我們指定SizeLimit爲1,庫仍然會拋出錯誤。

有沒有人對此問題有任何見解/建議?我們非常接近這個工作,只需要解決這個最後的問題。

+0

有多少目錄條目符合您的搜索條件?如果刪除SizeLimit行會發生什麼?似乎sizelimit將失敗,如果它的值低於服務器頁面大小。我想你應該嘗試發佈分頁搜索請參閱http://stackoverflow.com/q/1646518/1236044 – jbl

+0

我沒有發出請求中的分頁搜索控件,但得到了一個響應,該服務器不支持分頁搜索。 –

+0

我不知道有多少條目可以匹配我的搜索,但我只需要其中的100條。代碼的目的是創建一個在LDAPS中爲我們的產品執行「用戶搜索」的組件 - 這個庫不是法蘭庫 - 我們希望它是一個非常堅固的LDAPS用戶搜索(適配器模式)庫,以便我們可以提供這給我們的客戶。所以我無法預測用戶的輸入以及這可能對圖書館有多少結果。 –

回答

1

事實證明,這個工作:你得到一個DirectoryResponse類作爲DirectoryOperationException.Response財產

  try 
      { 
       response = (SearchResponse)con.SendRequest(request); 

       return response.Entries.Cast<SearchResultEntry>() 
        .Select(entry => entry.Attributes) 
        .Select(x => GetADUserSearchItemFromADProperties(x, logMessage)) 
        .Where(user => user.HasName) 
        .Cast<IUserSearchItem>(); 
      } 
      catch (DirectoryOperationException ex) 
      { 
       response = (SearchResponse) ex.Response; 
       return response.Entries.Cast<SearchResultEntry>() 
        .Select(entry => entry.Attributes) 
        .Select(x => GetADUserSearchItemFromADProperties(x, logMessage)) 
        .Where(user => user.HasName) 
        .Cast<IUserSearchItem>(); 
      } 

MSDN文檔。但是,您可以將此屬性轉換爲SearchResponse類型,然後使用SearchResponse.Entries屬性獲取您在觸碰指定的SizeLimit之前收到的條目。

我已經試過這個,我得到了預期的結果,我只是有點不高興,我不得不使用異常來執行操作。

+2

我認爲這個解決方案的一個問題是你沒有得到所有的搜索響應,只是響應SizeLimit。更正確的解決方案是提取您從Ex.Response收到的響應,然後重新運行SendRequest,但以某種方式將範圍限制爲您尚未檢索到的內容...... – Irinotecan

6

您應該使用類似於此功能的cookie。 該函數返回SearchResponse對象的集合,調用者應循環該集合。

private List<SearchResponse> SearchDirectory(string distinguishedName, string searchFilter, System.DirectoryServices.Protocols.SearchScope searchScope, params string[] attributeList) 
{ 
    List<SearchResponse> result = new List<SearchResponse>(); 
    SearchResponse response = null; 
    int maxResultsToRequest = 100; 
    try 
    { 
     PageResultRequestControl pageRequestControl = new PageResultRequestControl(maxResultsToRequest); 

     // used to retrieve the cookie to send for the subsequent request 
     PageResultResponseControl pageResponseControl; 
     SearchRequest searchRequest = new SearchRequest(distinguishedName, searchFilter, searchScope, attributeList); 
     searchRequest.Controls.Add(pageRequestControl); 

     while (true) 
     { 
      response = (SearchResponse)connection.SendRequest(searchRequest); 
      result.Add(response); 
      pageResponseControl = (PageResultResponseControl)response.Controls[0]; 
      if (pageResponseControl.Cookie.Length == 0) 
       break; 
      pageRequestControl.Cookie = pageResponseControl.Cookie; 
     } 
    } 
    catch (Exception e) 
    { 
     // do something with the error 

    } 
    return result; 
}