SharePoint: Allow web part to use System.DirectoryServices

A web part I developed needed to access Active Directory. A lot of posts say to just set the site’s trust level to Full, but that is a security risk.

The solution I found was to use a wss_custom trust level.

First, I copied the wss_minimal.config file in the CONFIG file of the 14-hive and named it wss_custom.config.

I then modified it as described in this post: http://www.derkeiler.com/Newsgroups/microsoft.public.dotnet.security/2004-10/0240.html

I added this to <SecurityClasses>:

< SecurityClass Name=”DirectoryServicesPermission”  Description=”System.DirectoryServices.DirectoryServicesPermission,  System.DirectoryServices, Version=1.0.5000.0, Culture=neutral,  PublicKeyToken=b03f5f7f11d50a3a”/>

Then I added the “DirectoryServicesPermission” to the “NamedPermissionSet” of “ASP.NET”:
<PermissionSet class=”NamedPermissionSet” version=”1″  Name=”ASP.Net”>
<IPermission class=”DirectoryServicesPermission” version=”1″  Unrestricted=”true”/> 
</PermissionSet>

[Note: I didn’t remove the other entries in those two sections.]

In the web.config file, I added this to the <securityPolicy> settings:

<trustLevel name=”WSS_Custom” policyFile=”C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\config\wss_custom.config” />

Next, I changed the trust level in the web.config file to WSS_Custom.

<trust level=”WSS_Custom” originUrl=”” />

[In addition to the post referenced above, this post helped me understand the steps to use a customized Code Access Security policy: http://blog.tylerholmes.com/2008/11/creating-custom-cas-policy-file-for.html]

In my web part C# code, I used PrincipalContext with a user with appropriate AD permissions:

PrincipalContext cxt = new PrincipalContext(ContextType.Domain, sDomain, sUser, sPwd);

using (UserPrincipal user = UserPrincipal.FindByIdentity(cxt, sAccountName))

{

DirectoryEntry entry = user.GetUnderlyingObject() as DirectoryEntry;

DirectorySearcher searcher = new DirectorySearcher(entry);

searcher.PropertiesToLoad.Add(“proxyAddresses”);

searcher.Filter = “(&(objectClass=user)(|(sAMAccountName=” + sAccountName + “)))”;

SearchResult result = searcher.FindOne();

if (result == null)

{

litResult.Text += “Error: User not found.”;

}

else

{

//do something

}

}

entry.Close();

entry.Dispose();

searcher.Dispose();

cxt.Dispose();

Sending Email via PowerShell and EWS

Just a sample script. I forgot that the message body needed to be converted to a string format and, as this script was being called by a back end process, it took me a while to figure out what the error was.

Code:

 

Add-Type -Path ‘F:\Program Files\Microsoft\Exchange\Web Services\2.0\Microsoft.Exchange.WebServices.dll’

#Create the EWS service object
$service = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService -ArgumentList Exchange2010_SP1

#Set the credentials for Exchange Online
#$service.Credentials = New-Object Microsoft.Exchange.WebServices.Data.WebCredentials -ArgumentList `
#$Credential.UserName, $Credential.GetNetworkCredential().Password
$service.UseDefaultCredentials = $true
$service.AutoDiscoverUrl(“sender@domain.com”)

#Determine the EWS endpoint using autodiscover
#$service.AutodiscoverUrl($Credential.UserName, {$true})

#Get the email body
$body = Get-Content “C:\Files\EmailTemplate.htm”
$body = $body -replace “Placeholder”, $Placeholder

#Have to convert the object to a string to use in the mail body.
[string]$msgBody = $body

#Create the email message and set the Subject and Body
$message = New-Object Microsoft.Exchange.WebServices.Data.EmailMessage -ArgumentList $service
$message.Body.BodyType = ‘HTML’
$message.From = “sender@domain.com”
$message.Subject = “A message for you”
$message.Body = $msgBody

$message.ToRecipients.Add($CreatorEmail)

#Send the message and save a copy in the users Sent Items folder (Alt is message.Send which will not save a copy.)
$message.SendAndSaveCopy()

Query to Find Disconnected Objects in the Metaverse

I needed a query to figure out which users in the metaverse were not connected to AD. With help from Carol Wapshere’s post on querying the metaverse (http://www.wapshere.com/missmiis/sql-query-find-metaverse-objects-with-n-connectors), I came up with this:

select EmployeeID from mms_metaverse where object_type =‘person’ and object_id not in

(select mv_object_id from dbo.mms_connectorspace cs

join dbo.mms_management_agent ma on

cs.ma_id = ma.ma_id

join dbo.mms_csmv_link mv on

mv.cs_object_id = cs.object_id

where ma.ma_name =‘ADMA’and object_type =‘user’)

AttributeNameViolatesSchema InvalidRepresentationException

I recently added a new attribute and binding in the FIM portal. After refreshing the FIM MA schema I added an attribute flow to this new attribute and received AttributeNameViolatesSchema InvalidRepresentationException exceptions.

Not sure why, but restarting the FIM Service, FIM Sync Service and doing an iisreset fixed the problem. Perhaps the FIM Sync Service restart wasn’t necessary… But I’m not sure at this point.

FIM Performance

Had a weird situation for a few days where all update or delete requests to the FIM portal were timing out–but retrieving data worked just fine.

Running this command against the FIMService DB seems to have helped:

exec sp_updatestats ‘resample’

Several sites led me to the solution here: http://social.msdn.microsoft.com/Forums/sqlserver/en-US/f0692fe1-f2e1-4cb9-9fdb-0cf27077bc39/update-stats-with-full-scan-on-database