2015-10-16 8 views
16

ho il seguente codice per cercare la rubrica globale da una certa stringa:Durante la ricerca Global Address List, c'è un modo per fare una ricerca parziale e non solo un "startsWith"

"CONF"

var esb = new ExchangeServiceBinding(); 
esb.Url = @"https://myurl.com/EWS/Exchange.asmx"; 

esb.Credentials = new NetworkCredential(_user,_pwd, _domain); 

var rnType = new ResolveNamesType {ReturnFullContactData = true, UnresolvedEntry = "CONF"}; 

ResolveNamesResponseType response = esb.ResolveNames(rnType); 
ArrayOfResponseMessagesType responses = resolveNamesResponse.ResponseMessages; 
var responseMessage = responses.Items[0] as ResolveNamesResponseMessageType; 

ResolutionType[] resolutions = responseMessage.ResolutionSet.Resolution; 

il problema è che sembra stia facendo un "inizia con" cercare quindi ho un nome chiamato:

"CONF-123" verrà visualizzato, ma se ho un nome "JOE-CONF "allora non lo farà.

Come posso fare una ricerca stringa parziale su questa linea

var rnType = new ResolveNamesType {ReturnFullContactData = true, UnresolvedEntry = "CONF-"}; 

Speravo ci fosse qualcosa di simile:

var rnType = new ResolveNamesType {ReturnFullContactData = true, UnresolvedEntry = "%CONF-%"}; 

ma questo non sembra funzionare.

+4

la vostra ricerca di 'CONF-', ma affermando che 'JOE-CONF' non compare nel ritorno. Non penserei che sarebbe dato che il '-' è dopo il 'CONF', cosa succede se si usa 'CONF' senza '-'. – Ilnetd

+0

quello era un errore di battitura. . Ho aggiornato la domanda – leora

+0

Stai ancora cercando una soluzione? – rsteward

risposta

0

Una ricerca ambigua su un campo di testo indicizzato può essere eseguita solo con prefisso (o suffisso ...). Ecco perché Exchange implementa probabilmente la query come LIKE 'CONF%'.

Ho esaminato la documentazione e non è possibile ignorarla: la scansione completa della tabella (che dovrebbe essere il caso di% CONF%) non sembra avere senso.

5

MODIFICA: gen 4,2016 - Aggiunto codice di esempio per la ricerca di annunci.

Cosa non funzionerà

Ricerca GAL tramite ResolveNames utilizza sempre partita prefisso-stringa per la risoluzione dei nomi ambigui (ARN). Sebbene la documentazione EWS non lo dica esplicitamente, la documentazione di Exchange ActiveSync. EWS ed Exchange ActiveSync sono solo protocolli; entrambi si basano su ARN sottostanti, quindi si è bloccati con la corrispondenza prefisso, indipendentemente dal fatto che si utilizzi il protocollo ActiveSync o EWS.

Ecco la citazione pertinente documentazione di Exchange ActiveSync (https://msdn.microsoft.com/en-us/library/ee159743%28v=exchg.80%29.aspx)

La stringa di query di testo che viene fornito al comando di ricerca viene utilizzato in un match prefix-stringa

.

cosa funzionerà

La cosa migliore da fare dipende dal vostro caso d'uso, ma qui ci sono alcune idee:

Ricerca Active Directory nel programma client (il programma che contiene il codice che avete mostrato nella tua domanda)

Imposta il tuo servizio per cercare il GAL. Il tuo programma client si collegherebbe sia a Exchange che al tuo servizio. Oppure il tuo servizio potrebbe proxy EWS, in modo che il programma client deve connettersi solo al tuo servizio.

In che modo è possibile ottenere i dati GAL?Un modo sarebbe quello di utilizzare EWS ResolveNames ripetutamente, per ottenere i dati GAL, 100 voci alla volta e memorizzare questi dati nel servizio. Prima di tutto, recupera tutti i "a", quindi tutti i "b", ecc. Naturalmente, ci possono essere più di 100 "a" nel GAL, quindi solo ottenere tutti i "a" potrebbe prendere più ricerche - costruisci la stringa di ricerca successiva, in base all'ultima voce restituita da ogni ricerca. Questo può essere lento e doloroso. Probabilmente vorrai memorizzare questi dati in un database e aggiornarlo periodicamente.

È inoltre possibile accedere a GAL tramite MAPI. È possibile utilizzare direttamente MAPI (https://msdn.microsoft.com/en-us/library/cc765775%28v=office.12%29.aspx) o tramite una libreria di supporto come Redemption (http://www.dimastr.com/redemption/home.htm). Sia che si utilizzi MAPI direttamente o tramite Redemption, sarà necessario installare Outlook (o Exchange) sul computer su cui è in esecuzione il codice. A causa di questa restrizione, potrebbe essere preferibile non utilizzare MAPI nel programma client, ma inserirlo in un servizio in esecuzione su alcuni server e fare in modo che il programma client si connetta a tale servizio.

codice degli annunci di esempio

Un altro codice di esempio risposta fornita per la ricerca di Active Directory. Sto aggiungendo un esempio di codice che potrebbe essere più adatto all'uso generico da parte di persone che potrebbero trovare questa domanda attraverso la ricerca. Rispetto agli altri di esempio, il codice qui sotto presenta i seguenti miglioramenti:

  • Se la stringa di ricerca contiene caratteri speciali (come parentesi), essi sono sfuggiti, in modo che la stringa di filtro costruito è valida.

  • Ricerca per samaccountname molti non sono sufficienti. Se "David Smith" ha nome account "dsmith", la ricerca di "David" da parte di samaccountname non lo troverà. Il mio esempio mostra come cercare per più campi e fornisce alcuni dei campi che si possono voler cercare.

  • L'avvio da una radice come "GC:" è più efficace rispetto al tentativo di creare una voce LDAP da Domain.GetComputerDomain().

  • Tutti i IDisposable s devono essere smaltiti (di solito li utilizza in un costrutto using).

    // Search Active Directory users. 
    public static IEnumerable<DirectoryEntry> SearchADUsers(string search) { 
        // Escape special characters in the search string. 
        string escapedSearch = search.Replace("*", "\\2a").Replace("(", "\\28") 
         .Replace(")", "\\29").Replace("/", "\\2f").Replace("\\", "\\5c"); 
    
        // Find entries where search string appears in ANY of the following fields 
        // (you can add or remove fields to suit your needs). 
        // The '|' characters near the start of the expression means "any". 
        string searchPropertiesExpression = string.Format(
         "(|(sn=*{0}*)(givenName=*{0}*)(cn=*{0}*)(dn=*{0}*)(samaccountname=*{0}*))", 
         escapedSearch); 
    
        // Only want users 
        string filter = "(&(objectCategory=Person)(" + searchPropertiesExpression + "))"; 
    
        using (DirectoryEntry gc = new DirectoryEntry("GC:")) { 
         foreach (DirectoryEntry root in gc.Children) { 
          try { 
           using (DirectorySearcher s = new DirectorySearcher(root, filter)) { 
            s.ReferralChasing = ReferralChasingOption.All; 
            SearchResultCollection results = s.FindAll(); 
            foreach (SearchResult result in results) { 
             using (DirectoryEntry de = result.GetDirectoryEntry()) { 
              yield return de; 
             } 
            } 
           } 
          } finally { 
           root.Dispose(); 
          } 
         } 
        } 
    } 
    
+0

Apprezzo che tu abbia condiviso una migliore implementazione di Ricerca AD. Ma per favore sii gentile/educato e usa parole come "per migliorare la risposta sopra", "per aggiungerlo", ecc. Ti invito a non usare parole/suoni come "La risposta di sopra ha molte carenze", "La mia risposta è meglio". Tutti qui sono per aiutare, imparare gli uni dagli altri. Non c'è dubbio che ogni pezzo di codice abbia possibilità di miglioramento. Il nocciolo del problema che leora sta affrontando è la ricerca con contiene la corrispondenza. Ho cercato di rispondere, piuttosto che concentrarmi sulla scrittura del codice più efficiente, che credo che leora non abbia problemi a scrivere. –

+0

Hai ragione, Abhijit. Grazie per avermi insegnato le buone maniere. Ho modificato la mia formulazione. – George

4

Sebbene ricerca con caratteri jolly non è possibile in EWS, è possibile in cerca dC. Le query di AD supportano i caratteri jolly. Ad esempio, * CONF * può essere cercato in AD, che restituirà tutti i risultati che contengono "CONF". In base ai risultati, interrogare EWS per un oggetto di scambio corrispondente. È necessario trovare un parametro con il quale è possibile trovare la voce EWS corrispondente. Suppongo che l'indirizzo email (username) dovrebbe essere sufficiente per trovare l'oggetto di scambio corrispondente.

dC codice Ricerca frammento ...

private SearchResultCollection SearchByName(string username, string password, string searchKeyword) 
{ 
    DirectorySearcher ds = new DirectorySearcher(new DirectoryEntry("LDAP://" + Domain.GetComputerDomain().ToString().ToLower(), username, password)); 
    ds.Filter = "(&((&(objectCategory=Person)(objectClass=User)))(samaccountname=*" + searchKeyword + "*))"; 
    ds.SearchScope = SearchScope.Subtree; 
    ds.ServerTimeLimit = TimeSpan.FromSeconds(90); 
    return ds.FindAll(); 
} 

dC Query Esempio here.

0

Ho anche cercato di cercare il GAL da PHP utilizzando php-ews. Su una pagina web l'utente inizia a inserire il nome da cercare, una volta inseriti 2 caratteri, viene effettuata una chiamata a read_contacts.php passando i 2 caratteri immessi. read_contacts.php utilizza la richiesta EWS ResolveNames per recuperare un elenco limitato di contatti. Il codice quindi filtra alcuni criteri e controlla anche che displayName inizi con i caratteri immessi.Questo poi restituisce l'elenco filtrato:

<?php 
$staffName = $_GET['q'];  
require_once './php-ews/EWSType.php'; 
require_once './php-ews/ExchangeWebServices.php'; 
require_once 'php-ews/EWSType/RestrictionType.php'; 
require_once 'php-ews/EWSType/ContainsExpressionType.php'; 
require_once 'php-ews/EWSType/PathToUnindexedFieldType.php'; 
require_once 'php-ews/EWSType/ConstantValueType.php'; 
require_once 'php-ews/EWSType/ContainmentModeType.php'; 
require_once 'php-ews/EWSType/ResolveNamesType.php'; 
require_once 'php-ews/EWSType/ResolveNamesSearchScopeType.php'; 
require_once 'php-ews/NTLMSoapClient.php'; 
require_once 'php-ews/NTLMSoapClient/Exchange.php'; 

$host = '[exchange server]'; 
$user = '[exchange user]'; 
$password = '[exchange password]'; 

$ews = new ExchangeWebServices($host, $user, $password); 

$request = new EWSType_ResolveNamesType(); 

$request->ReturnFullContactData = true; 
$request->UnresolvedEntry = $staffName; 


$displayName = ''; 
$i = 0; 
$staff_members = false; 
$response = $ews->ResolveNames($request); 
if ($response->ResponseMessages->ResolveNamesResponseMessage->ResponseClass == 'Error' && $response->ResponseMessages->ResolveNamesResponseMessage->MessageText == 'No results were found.') { 
} 
else { 
    $numNamesFound = $response->ResponseMessages->ResolveNamesResponseMessage->ResolutionSet->TotalItemsInView; 
    $i2=0; 
    for ($i=0;$i<$numNamesFound;$i++) { 
     if ($numNamesFound == 1) { 
      $displayName = $response->ResponseMessages->ResolveNamesResponseMessage->ResolutionSet->Resolution->Contact->DisplayName; 
     } 
     else { 
      $displayName = $response->ResponseMessages->ResolveNamesResponseMessage->ResolutionSet->Resolution[$i]->Contact->DisplayName; 
     } 
     echo "DisplayName: " . $displayName . "\n";  
     if (stripos($displayName, 'External') == true) { 
     } 
     else { 
      $searchLen = strlen($staffName); 
      if (strcasecmp(substr($displayName, 0, $searchLen), $staffName) == 0) { 
       if ($numNamesFound == 1) { 
        $emailAddress = $response->ResponseMessages->ResolveNamesResponseMessage->ResolutionSet->Resolution->Mailbox->EmailAddress; 
       } 
       else { 
        $emailAddress = $response->ResponseMessages->ResolveNamesResponseMessage->ResolutionSet->Resolution[$i]->Mailbox->EmailAddress; 
       } 
       $staff_members[$i2] = array('name' => $displayName,'email' => $emailAddress); 
       $i2++; 
      } 
     } 
    } 
    $staffJson = json_encode($staff_members); 
echo $staffJson; 
} 

Il più delle volte questo sembra funzionare, vale a dire: 'mi', 'jo' torna Mike, Michael, o Joe, John, tranne quando ho mandato 'Si' o 'si', per Simon, quindi la chiamata ResolveNames restituisce le prime 100 voci dal GAL.

Per ora ho aumentato il numero minimo di caratteri da inserire in 3, cioè: 'sim' e questo funziona. Il problema sarà quando avremo personale con solo 2 nomi di battesimo.

Ho solo pensato di condividere il codice per vedere se è d'aiuto e per vedere se qualcuno sa perché il mio "si" non funziona correttamente.

Io sono l'accesso di Exchange 2010

Problemi correlati