<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Toth’s Tales from the Trenches</title>
	<atom:link href="http://vspug.com/toth/feed/" rel="self" type="application/rss+xml" />
	<link>http://vspug.com/toth</link>
	<description>Just another VSPUG - Virtual SharePoint User Group weblog</description>
	<lastBuildDate>Mon, 13 Apr 2009 17:29:00 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>SharePoint Field Names have 32 Character Limit &#8211; So Do Replicated Profile Property Names</title>
		<link>http://vspug.com/toth/2009/04/13/sharepoint-field-names-have-32-character-limit-so-do-replicated-profile-property-names/</link>
		<comments>http://vspug.com/toth/2009/04/13/sharepoint-field-names-have-32-character-limit-so-do-replicated-profile-property-names/#comments</comments>
		<pubDate>Mon, 13 Apr 2009 17:29:00 +0000</pubDate>
		<dc:creator>adamtoth</dc:creator>
		
		<guid isPermaLink="false"></guid>
		<description><![CDATA[Note: Cross posted from Life on Planet Groove.
Permalink
I ran into a situation where I created a User Profile Property with the Replicable checkbox set, which had a really long name. There were no errors when saving the profile property, however later on I started receiving errors in the Event Log:
failure trying to synch site [guid] [...]]]></description>
			<content:encoded><![CDATA[<p><b>Note:</b> Cross posted from <a href="http://www.lifeonplanetgroove.com/blog">Life on Planet Groove</a>.<br />
<br /><a href="http://www.lifeonplanetgroove.com/blog/index.php/2009/04/13/sharepoint-field-names-have-32-character-limit-so-do-replicated-profile-property-names/">Permalink</a></p>
<p>I ran into a situation where I created a User Profile Property with the Replicable checkbox set, which had a really long name. There were no errors when saving the profile property, however later on I started receiving errors in the Event Log:</p>
<p>failure trying to synch site [guid] for ContentDB [guid] WebApp [guid].&nbsp; Exception message was A WSS internal name for profile property &#39;ProfilePropertyWithReallyLongName&#39; could not be found..</p>
<p>Apparently SharePoint has a limit of 32 characters for Internal Field Names. This will also apply to Replicable User Profile Properties since they will get synced down to the WSS Content DB in the UserInfo list.</p>
]]></content:encoded>
			<wfw:commentRss>http://vspug.com/toth/2009/04/13/sharepoint-field-names-have-32-character-limit-so-do-replicated-profile-property-names/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SharePoint May Break Hyperlinks in Workflow Task Emails</title>
		<link>http://vspug.com/toth/2009/04/10/sharepoint-may-break-hyperlinks-in-workflow-task-emails/</link>
		<comments>http://vspug.com/toth/2009/04/10/sharepoint-may-break-hyperlinks-in-workflow-task-emails/#comments</comments>
		<pubDate>Fri, 10 Apr 2009 16:43:00 +0000</pubDate>
		<dc:creator>adamtoth</dc:creator>
		
		<guid isPermaLink="false"></guid>
		<description><![CDATA[Note: Cross posted from Life on Planet Groove.
Permalink
I ran into an issue where hyperlinks in workflow task emails where being automatically changed by SharePoint from absolute hyperlinks to relative ones.
Scenario:

You create a custom Visual Studio workflow and use the CreateTask activity.
You set your SPWorkflowTaskProperties.Description property to some HTML text.
In your Description HTML text, you have [...]]]></description>
			<content:encoded><![CDATA[<p><b>Note:</b> Cross posted from <a href="http://www.lifeonplanetgroove.com/blog">Life on Planet Groove</a>.<br />
<br /><a href="http://www.lifeonplanetgroove.com/blog/index.php/2009/04/09/sharepoint-may-break-hyperlinks-in-workflow-task-emails/">Permalink</a></p>
<p>I ran into an issue where hyperlinks in workflow task emails where being automatically changed by SharePoint from absolute hyperlinks to relative ones.</p>
<p><b>Scenario:</b></p>
<ol>
<li>You create a custom Visual Studio workflow and use the CreateTask activity.</li>
<li>You set your SPWorkflowTaskProperties.Description property to some HTML text.</li>
<li>In your Description HTML text, you have an html hyperlink &lt;a&gt; tag whose href=&rdquo;&rdquo; attribute contains an absolute hyperlink to a resource in the same SharePoint farm (i.e. a list item).</li>
<li>Example: &ldquo;Please review &lt;a href=&rdquo;http://yourserver/site/lists/yourlist/dispform.aspx?ID=1&rdquo;&gt;contract #12345&lt;/a&gt;&rdquo;.</li>
</ol>
<p><b>Goal:</b></p>
<p>Users will receive the task email, and be able to click on the absolute URL in the email body to navigate to the SharePoint resource.</p>
<p><b>Problem:</b></p>
<p>It appears that SharePoint parses this HTML and readjusts the hyperlink and makes it relative.</p>
<p>Example: &ldquo;Please review &lt;a href=&rdquo;/lists/yourlist/dispform.aspx?ID=1&rdquo;&gt;contract #12345&lt;/a&gt;&rdquo;</p>
<p>This effectively breaks the hyperlink in the email client.</p>
<p>The only workaround was to get rid of the &lt;a&gt; tag and write out the hyperlink in full. For example:</p>
<p>&ldquo;Please review contract #12345 (<a rel="nofollow" href="http://yourserver/site/lists/yourlist/dispform.aspx?ID=1">http://yourserver/site/lists/yourlist/dispform.aspx?ID=1</a>)&rdquo;.</p>
<p>In this manner, SharePoint did not adjust the hyperlink at all.</p>
]]></content:encoded>
			<wfw:commentRss>http://vspug.com/toth/2009/04/10/sharepoint-may-break-hyperlinks-in-workflow-task-emails/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>BDC Error &#8211; Type does not match DotNet type of TypeDescriptor</title>
		<link>http://vspug.com/toth/2009/04/09/bdc-error-type-does-not-match-dotnet-type-of-typedescriptor/</link>
		<comments>http://vspug.com/toth/2009/04/09/bdc-error-type-does-not-match-dotnet-type-of-typedescriptor/#comments</comments>
		<pubDate>Thu, 09 Apr 2009 18:42:00 +0000</pubDate>
		<dc:creator>adamtoth</dc:creator>
		
		<guid isPermaLink="false"></guid>
		<description><![CDATA[Note: Cross posted from Life on Planet Groove.
Permalink
I ran into a BDC error, &#8220;Type does not match DotNet type of TypeDescriptor&#8221;, with a particular application definition I wrote. In this case, I had a specific finder method that took one input parameter (the identifier) that was of type System.Decimal. It turns out I didn&#8217;t specify [...]]]></description>
			<content:encoded><![CDATA[<p><b>Note:</b> Cross posted from <a href="http://www.lifeonplanetgroove.com/blog">Life on Planet Groove</a>.<br />
<br /><a href="http://www.lifeonplanetgroove.com/blog/index.php/2009/04/09/bdc-error-type-does-not-match-dotnet-type-of-typedescriptor/">Permalink</a></p>
<p>I ran into a BDC error, &ldquo;Type does not match DotNet type of TypeDescriptor&rdquo;, with a particular application definition I wrote. In this case, I had a specific finder method that took one input parameter (the identifier) that was of type System.Decimal. It turns out I didn&rsquo;t specify a default value in the TypeDescriptor for this input parameter in my XML definition. It looks like when you don&rsquo;t set a default value, it will automatically set one for you and assign it a type of System.String. I was able to see this when I exported the BDC definition fresh, and noticed that SharePoint automatically added this default value and type for me.</p>
<p>Rule of thumb, always specify a default value for each input parameter.</p>
]]></content:encoded>
			<wfw:commentRss>http://vspug.com/toth/2009/04/09/bdc-error-type-does-not-match-dotnet-type-of-typedescriptor/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Workflow Task Locked when AssignedTo Changed to Support Multiple Selections</title>
		<link>http://vspug.com/toth/2009/04/03/workflow-task-locked-when-assignedto-changed-to-support-multiple-selections/</link>
		<comments>http://vspug.com/toth/2009/04/03/workflow-task-locked-when-assignedto-changed-to-support-multiple-selections/#comments</comments>
		<pubDate>Fri, 03 Apr 2009 17:55:00 +0000</pubDate>
		<dc:creator>adamtoth</dc:creator>
		
		<guid isPermaLink="false"></guid>
		<description><![CDATA[Note: Cross posted from Life on Planet Groove.
Permalink
This is an old one, but some co-workers ran into this again recently on a project.
When you have a SharePoint workflow that assigns tasks (either Designer or Visual Studio workflow), when you change the Assigned To column on the task list to allow Multiple Selections, your workflow will [...]]]></description>
			<content:encoded><![CDATA[<p><b>Note:</b> Cross posted from <a href="http://www.lifeonplanetgroove.com/blog">Life on Planet Groove</a>.<br />
<br /><a href="http://www.lifeonplanetgroove.com/blog/index.php/2009/04/03/workflow-task-locked-when-assignedto-changed-to-support-multiple-selections/">Permalink</a></p>
<p>This is an old one, but some co-workers ran into this again recently on a project.</p>
<p>When you have a SharePoint workflow that assigns tasks (either Designer or Visual Studio workflow), when you change the Assigned To column on the task list to allow Multiple Selections, your workflow will hang and become unresponsive when a user edits the task. You&rsquo;ll receive a message about the task being locked (&ldquo;This task is currently locked by a running workflow and cannot be edited&rdquo;). OnTaskChanged events will no longer fire and your workflow will be stuck and unrecoverable.</p>
<p>There is no hotfix or workaround for this, so you simply cannot have the assigned to column support multiple users or groups. Just use a single group instead.</p>
<p>Following are some other resources discussing this:</p>
<ul>
<li><a title="http://www.eggheadcafe.com/conversation.aspx?messageid=32931131&amp;threadid=32931131" href="http://www.eggheadcafe.com/conversation.aspx?messageid=32931131&amp;threadid=32931131">http://www.eggheadcafe.com/conversation.aspx?messageid=32931131&amp;threadid=32931131</a></li>
<li><a title="http://connect.microsoft.com/wf/feedback/ViewFeedback.aspx?FeedbackID=273487" href="http://connect.microsoft.com/wf/feedback/ViewFeedback.aspx?FeedbackID=273487">http://connect.microsoft.com/wf/feedback/ViewFeedback.aspx?FeedbackID=273487</a></li>
<li><a title="http://social.technet.microsoft.com/Forums/en-US/sharepointworkflow/thread/8ec834b6-5408-4079-bdfb-b88d341b36bf/" href="http://social.technet.microsoft.com/Forums/en-US/sharepointworkflow/thread/8ec834b6-5408-4079-bdfb-b88d341b36bf/">http://social.technet.microsoft.com/Forums/en-US/sharepointworkflow/thread/8ec834b6-5408-4079-bdfb-b88d341b36bf/</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://vspug.com/toth/2009/04/03/workflow-task-locked-when-assignedto-changed-to-support-multiple-selections/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>This Blog has Moved</title>
		<link>http://vspug.com/toth/2009/03/05/this-blog-has-moved/</link>
		<comments>http://vspug.com/toth/2009/03/05/this-blog-has-moved/#comments</comments>
		<pubDate>Thu, 05 Mar 2009 23:50:00 +0000</pubDate>
		<dc:creator>adamtoth</dc:creator>
		
		<guid isPermaLink="false"></guid>
		<description><![CDATA[This blog has now moved. I&#39;ll continue to cross post relevant SharePoint articles here, but if you would like to stay current with my latest postings, please follow me at the new location:
URL: http://www.lifeonplanetgroove.com
RSS Feed: http://feeds2.feedburner.com/LifeOnPlanetGrooveSharepoint
Thanks,
Adam
]]></description>
			<content:encoded><![CDATA[<p>This blog has now moved. I&#39;ll continue to cross post relevant SharePoint articles here, but if you would like to stay current with my latest postings, please follow me at the new location:</p>
<p>URL: <a href="http://www.lifeonplanetgroove.com">http://www.lifeonplanetgroove.com</a></p>
<p>RSS Feed: <a href="http://feeds2.feedburner.com/LifeOnPlanetGrooveSharepoint">http://feeds2.feedburner.com/LifeOnPlanetGrooveSharepoint</a></p>
<p>Thanks,</p>
<p>Adam</p>
]]></content:encoded>
			<wfw:commentRss>http://vspug.com/toth/2009/03/05/this-blog-has-moved/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Performance Optimizations for Large Programmatic User Profile Imports</title>
		<link>http://vspug.com/toth/2009/03/05/performance-optimizations-for-large-programmatic-user-profile-imports/</link>
		<comments>http://vspug.com/toth/2009/03/05/performance-optimizations-for-large-programmatic-user-profile-imports/#comments</comments>
		<pubDate>Thu, 05 Mar 2009 23:47:00 +0000</pubDate>
		<dc:creator>adamtoth</dc:creator>
		
		<guid isPermaLink="false"></guid>
		<description><![CDATA[Note: Cross posted from Life on Planet Groove. Permalink
I&#8217;m working on a project that imports over 1 million users from an Oracle database used with SharePoint/Forms Authentication into the SharePoint user profile store. This is done as a custom SharePoint timer job that pulls the users from the DB and creates/updates User Profiles through the [...]]]></description>
			<content:encoded><![CDATA[<p><b>Note:</b> Cross posted from <a href="http://www.lifeonplanetgroove.com/blog">Life on Planet Groove</a>. <br /><a href="http://www.lifeonplanetgroove.com/blog/index.php/2009/03/05/performance-optimizations-for-large-programmatic-user-profile-imports/">Permalink</a></p>
<p>I&rsquo;m working on a project that imports over 1 million users from an Oracle database used with SharePoint/Forms Authentication into the SharePoint user profile store. This is done as a custom SharePoint timer job that pulls the users from the DB and creates/updates User Profiles through the SharePoint API.</p>
<p>When running a job on a recordset of this size, there are several things to strive for:</p>
<ul>
<li>Limit the time that the process needs to run (jobs can take days and overlap themselves)</li>
<li>Reduce memory usage (the OWSTIMER.exe can already consume quite a bit with the regular timer jobs)</li>
</ul>
<p>Two ways you can achieve this:</p>
<ul>
<li>Avoid UserExists() method</li>
<li>Use a DataReader if possible&nbsp;&nbsp;</li>
</ul>
<h3>Avoid UserExists() method</h3>
<p>Most code samples on the web that deal with programmatic creation of User Profiles will show code such as this:</p>
<div style="border:1px solid gray;margin:20px 0px 10px;padding:4px;overflow:auto;font-size:8pt;width:97.5%;cursor:text;max-height:200px;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">
<div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">if</span> (profileManager.UserExists(accountName)</pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">    userProfile = profileManager.GetUserProfile(accountName)...</pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">else</span></pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">    userProfile = profileManager.CreateUserProfile(accountName)...</pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre>
</div>
</div>
<p>On small recordsets, this is fine, but for large recordsets the UserExists method represents a bottleneck that can increase the duration that your process runs. In addition, in the code above, you will unknowingly call this method a second useless time, because the CreateUserProfile() method internally calls UserExists() as well.</p>
<p>There are two ways to avoid this method:</p>
<ul>
<li>Cache profile IDs in a Dictionary/Hashtable type object</li>
<li>Use reflection to create user profiles</li>
</ul>
<h4>Cache Profile IDs (and MemberGroup IDs too)</h4>
<p>The UserProfileManager object is an IEnumerable that you can iterate over and access all the Profiles in SharePoint. Caching the IDs of these profiles up front enables you to index into a Dictionary object to see if your profile exists, rather than hitting SQL Server with UserExists(). The following code helped to reduce processing time significantly (you take a hit up front, but it&rsquo;s far less than the delay imposed by UserExists over large recordsets):</p>
<div style="border:1px solid gray;margin:20px 0px 10px;padding:4px;overflow:auto;font-size:8pt;width:97.5%;cursor:text;max-height:200px;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">
<div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">Dictionary&lt;<span style="color:#0000ff;">string</span>, Guid&gt; cachedProfiles = <span style="color:#0000ff;">new</span> Dictionary&lt;<span style="color:#0000ff;">string</span>, Guid&gt;();</pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">foreach</span>(UserProfile profile <span style="color:#0000ff;">in</span> profileManager)</pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">{</pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">    cachedProfiles.Add(profile.AccountName, profile.ID);</pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">...</pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">if</span>(cachedProfiles.ContainsKey(accountName)</pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">    ...</pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre>
</div>
</div>
<p>In addition, caching the Guid of the <a target="_blank" href="http://msdn.microsoft.com/en-us/library/microsoft.office.server.userprofiles.userprofile.aspx">UserProfile</a> lets you later use the overloaded method of GetUserProfile() that takes a Guid as a parameter, which seems to perform slightly better than the alternative that takes a string for AccountName.</p>
<p>This approach also works very well when importing large numbers of MemberGroups:</p>
<div style="border:1px solid gray;margin:20px 0px 10px;padding:4px;overflow:auto;font-size:8pt;width:97.5%;cursor:text;max-height:200px;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">
<div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">foreach</span> (MemberGroup memberGroup <span style="color:#0000ff;">in</span> memberGroupManager)</pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">    cachedMemberGroups.Add(memberGroup.DisplayName, memberGroup.Id);</pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre>
</div>
</div>
<p><b>NOTE:</b> If you are wondering why not simply cache the entire UserProfile in the Dictionary (Dictionary&lt;string, UserProfile&gt;), the memory usage for this will be much higher, which will undo any gains by avoiding UserExists().</p>
<h4>Use Reflection to Create User Profiles</h4>
<p>The UserProfileManager&rsquo;s CreateUserProfile() method internally calls the UserExists method, and then calls an internal constructor on the UserProfile object to actually create the profile. By using reflection, you can call this internal constructor yourself and avoid UserExists():</p>
<div style="border:1px solid gray;margin:20px 0px 10px;padding:4px;overflow:auto;font-size:8pt;width:97.5%;cursor:text;max-height:200px;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">
<div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#008000;">// Get some reflected information about the UserProfile object for later use</span></pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">ConstructorInfo ci = <span style="color:#0000ff;">typeof</span>(UserProfile).GetConstructor(</pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">BindingFlags.NonPublic | BindingFlags.Instance,</pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">null</span>,</pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">new</span> Type[] { <span style="color:#0000ff;">typeof</span>(UserProfileManager), <span style="color:#0000ff;">typeof</span>(<span style="color:#0000ff;">string</span>), <span style="color:#0000ff;">typeof</span>(<span style="color:#0000ff;">string</span>) },</pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">null</span>);</pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre>
</div>
</div>
<p>Once you&rsquo;ve got the reflected information, you can use the following code to create your UserProfile:</p>
<div style="border:1px solid gray;margin:20px 0px 10px;padding:4px;overflow:auto;font-size:8pt;width:97.5%;cursor:text;max-height:200px;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">
<div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">if</span> (cachedProfiles.ContainsKey(accountName))</pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">    <span style="color:#008000;">// Get existing profile...</span></pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">else</span></pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">    <span style="color:#008000;">// Create new profile</span></pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">    UserProfile newProfile = (UserProfile)ci.Invoke(<span style="color:#0000ff;">new</span> <span style="color:#0000ff;">object</span>[] { profileManager, accountName, displayName });</pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre>
</div>
</div>
<p><b>NOTE:</b> I&rsquo;ve tried creating a user profile in this manner that already existed to see what would happen. The existing profile was updated, and I did not get any duplicate records in the SharePoint db. It appears the SQL under the hood already takes care of avoiding duplicates. General cautions about reflection still apply here though (API may change, etc.).</p>
<h3>Use a DataReader if Possible</h3>
<p>Instead of pulling a huge recordset into a DataTable, DataSet, or into a collection of custom objects, try to process your records one at a time using a data reader if your data source permits. This will keep memory usage down, as the garbage collector will dispose frequently any variables you create within a while(reader.Read()) loop. A DataTable with 1 million records in it will take up tons of memory on top of the large memory consumption that OWSTIMER.exe does already.</p>
<div style="border:1px solid gray;margin:20px 0px 10px;padding:4px;overflow:auto;font-size:8pt;width:97.5%;cursor:text;max-height:200px;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">
<div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">using</span> (OracleConnection conn = <span style="color:#0000ff;">new</span> OracleConnection(_connectionString))</pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">    <span style="color:#0000ff;">using</span> (OracleCommand cmd = <span style="color:#0000ff;">new</span> OracleCommand(_sqlGetAllUsers, conn))</pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">    {</pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">        conn.Open();</pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">        OracleDataReader rdr = cmd.ExecuteReader();</pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">        <span style="color:#0000ff;">if</span>(!rdr.HasRows())</pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">        {</pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">            <span style="color:#0000ff;">return</span>;</pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">        }</pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">&nbsp;</pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">        <span style="color:#0000ff;">while</span> (rdr.Read())</pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">        {</pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">            UserProfile profile = <span style="color:#0000ff;">null</span>;</pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">            <span style="color:#0000ff;">string</span> accountName = rdr[<span style="color:#006080;">&quot;ACCOUNT_NAME&quot;</span>] <span style="color:#0000ff;">as</span> <span style="color:#0000ff;">string</span>;</pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">            <span style="color:#0000ff;">string</span> firstName = rdr[<span style="color:#006080;">&quot;FIRST_NAME&quot;</span>] <span style="color:#0000ff;">as</span> <span style="color:#0000ff;">string</span>;</pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">            <span style="color:#0000ff;">string</span> lastName = rdr[<span style="color:#006080;">&quot;LAST_NAME&quot;</span>] <span style="color:#0000ff;">as</span> <span style="color:#0000ff;">string</span>;</pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">            <span style="color:#0000ff;">if</span> (cachedProfiles.ContainsKey(accountName))</pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">            {</pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">                profile = profileManager.GetUserProfile(cachedProfiles[accountName]);</pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">            }</pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">            <span style="color:#0000ff;">else</span></pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">            {</pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">                profile = (UserProfile)ci.Invoke(<span style="color:#0000ff;">new</span> <span style="color:#0000ff;">object</span>[] { profileManager, accountName, displayName });</pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">                cachedProfiles.Add(accountName, profile.ID);</pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">            }</pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">            <span style="color:#0000ff;">if</span> (!<span style="color:#0000ff;">string</span>.IsNullOrEmpty(firstName))</pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">            {</pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">                profile[<span style="color:#006080;">&quot;FirstName&quot;</span>].Value = firstName;</pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">            }</pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">            <span style="color:#0000ff;">if</span> (!<span style="color:#0000ff;">string</span>.IsNullOrEmpty(lastName))</pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">            {</pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">                profile[<span style="color:#006080;">&quot;LastName&quot;</span>].Value = lastName;</pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">            }</pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">            <span style="color:#008000;">// ... </span></pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">            profile.Commit();</pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">&nbsp;</pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">        }</pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">&nbsp;</pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">        rdr.Close();</pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">        rdr.Dispose();</pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">    }</pre>
<p>&nbsp;</p>
<pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre>
</div>
</div>
<p>Of course other best practices also apply, such as:</p>
<ul>
<li>Getting pages of records, rather than all at once</li>
<li>Implementing incremental change queries rather than all records all the time</li>
<li>Only getting what you need from the data source</li>
<li>Disposing your objects and data connections properly</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://vspug.com/toth/2009/03/05/performance-optimizations-for-large-programmatic-user-profile-imports/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Event Handler for Renaming List Item Attachments</title>
		<link>http://vspug.com/toth/2008/12/18/event-handler-for-renaming-list-item-attachments/</link>
		<comments>http://vspug.com/toth/2008/12/18/event-handler-for-renaming-list-item-attachments/#comments</comments>
		<pubDate>Thu, 18 Dec 2008 15:57:22 +0000</pubDate>
		<dc:creator>adamtoth</dc:creator>
		
		<guid isPermaLink="false"></guid>
		<description><![CDATA[I needed the ability to rename list item attachments automatically as attachments were uploaded. I wanted to prefix the filename with the current date/time so that 1) all files would have a unique filename and 2) the files would be sorted in the Display form for the item.
I created an event handler for the ItemAttachmentAdded [...]]]></description>
			<content:encoded><![CDATA[<p>I needed the ability to rename list item attachments automatically as attachments were uploaded. I wanted to prefix the filename with the current date/time so that 1) all files would have a unique filename and 2) the files would be sorted in the Display form for the item.</p>
<p>I created an event handler for the ItemAttachmentAdded event. It turns out that in the ItemAttachment&#8230; events, you cannot modify the attachment file in any way, including renaming it. The BeforeUrl and After Url properties are read-only, and there is no SPListItem in the SPItemEventProperties object to use. The only handle you can get to the actual file is to traverse the Attachments folder of the list until you get a reference to the actual SPFile object that represents the attachment. The SPFile object has only ReadOnly properties for Title/Name, so you cannot do anything there.</p>
<p>The only way I could find to perform a rename, was to get the binary Byte[] array of the file, create a new attachment with the proper file name, and then delete the original attachment. My code is below:</p>
<div style="border-right:gray 1px solid;padding-right:4px;border-top:gray 1px solid;padding-left:4px;font-size:8pt;padding-bottom:4px;margin:20px 0px 10px;overflow:auto;border-left:gray 1px solid;width:97.5%;cursor:text;max-height:200px;line-height:12pt;padding-top:4px;border-bottom:gray 1px solid;font-family:consolas, &#39;Courier New&#39;, courier, monospace;background-color:#f4f4f4;">
<div style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &#39;Courier New&#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;">
<pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &#39;Courier New&#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;border-bottom-style:none;"><span style="color:#008000;">/// &lt;summary&gt;</span></pre>
<pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &#39;Courier New&#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;"><span style="color:#008000;">/// Asynchronous event occurs after the attachment is added</span></pre>
<pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &#39;Courier New&#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;border-bottom-style:none;"><span style="color:#008000;">/// &lt;/summary&gt;</span></pre>
<pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &#39;Courier New&#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;"><span style="color:#008000;">/// &lt;param name=&quot;properties&quot;&gt;&lt;/param&gt;</span></pre>
<pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &#39;Courier New&#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;border-bottom-style:none;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">override</span> <span style="color:#0000ff;">void</span> ItemAttachmentAdded(SPItemEventProperties properties)</pre>
<pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &#39;Courier New&#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;">{</pre>
<pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &#39;Courier New&#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;border-bottom-style:none;">    <span style="color:#0000ff;">base</span>.ItemAttachmentAdded(properties);</pre>
<pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &#39;Courier New&#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;">&#160;</pre>
<pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &#39;Courier New&#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;border-bottom-style:none;">    <span style="color:#008000;">// Make sure we have at least one attachment (this should never happen, but just in case)</span></pre>
<pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &#39;Courier New&#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;">    <span style="color:#0000ff;">if</span> (properties.ListItem.Attachments.Count == 0)</pre>
<pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &#39;Courier New&#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;border-bottom-style:none;">    {</pre>
<pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &#39;Courier New&#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;">        <span style="color:#0000ff;">return</span>;</pre>
<pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &#39;Courier New&#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;border-bottom-style:none;">    }</pre>
<pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &#39;Courier New&#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;">&#160;</pre>
<pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &#39;Courier New&#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;border-bottom-style:none;">    <span style="color:#008000;">// Get a reference to the attachment</span></pre>
<pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &#39;Courier New&#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;">    SPFile attachment = properties.ListItem.ParentList.RootFolder.SubFolders[<span style="color:#006080;">&quot;Attachments&quot;</span>].SubFolders[properties.ListItemId.ToString()].Files[properties.ListItem.Attachments.Count - 1];</pre>
<pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &#39;Courier New&#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;border-bottom-style:none;">&#160;</pre>
<pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &#39;Courier New&#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;">    <span style="color:#008000;">// Get the raw data of the file</span></pre>
<pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &#39;Courier New&#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;border-bottom-style:none;">    <span style="color:#0000ff;">byte</span>[] content = attachment.OpenBinary();</pre>
<pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &#39;Courier New&#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;">&#160;</pre>
<pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &#39;Courier New&#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;border-bottom-style:none;">    <span style="color:#008000;">// Get the original attachment name</span></pre>
<pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &#39;Courier New&#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;">    <span style="color:#0000ff;">string</span> originalFileName = attachment.Name;</pre>
<pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &#39;Courier New&#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;border-bottom-style:none;">    <span style="color:#008000;">// Get the new file name with the date/time stamp</span></pre>
<pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &#39;Courier New&#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;">    <span style="color:#0000ff;">string</span> newFileName = GetFileNameWithDate(originalFileName);</pre>
<pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &#39;Courier New&#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;border-bottom-style:none;">&#160;</pre>
<pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &#39;Courier New&#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;">    <span style="color:#008000;">// Turn off events so that we don&#39;t get an infinite loop when we add back the attachment</span></pre>
<pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &#39;Courier New&#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;border-bottom-style:none;">    DisableEventFiring();</pre>
<pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &#39;Courier New&#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;">&#160;</pre>
<pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &#39;Courier New&#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;border-bottom-style:none;">    <span style="color:#008000;">// Delete the original attachment (we can&#39;t simply rename the attachment)</span></pre>
<pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &#39;Courier New&#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;">    properties.ListItem.Attachments.DeleteNow(originalFileName);</pre>
<pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &#39;Courier New&#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;border-bottom-style:none;">    </pre>
<pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &#39;Courier New&#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;">    <span style="color:#008000;">// Add the attachment back with the new filename</span></pre>
<pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &#39;Courier New&#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;border-bottom-style:none;">    properties.ListItem.Attachments.AddNow(newFileName, content);</pre>
<pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &#39;Courier New&#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;">&#160;</pre>
<pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &#39;Courier New&#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;border-bottom-style:none;">    <span style="color:#008000;">// Turn on events again</span></pre>
<pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &#39;Courier New&#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;">    EnableEventFiring();</pre>
<pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &#39;Courier New&#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;border-bottom-style:none;">&#160;</pre>
<pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &#39;Courier New&#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;">}</pre>
<pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &#39;Courier New&#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;border-bottom-style:none;">&#160;</pre>
<pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &#39;Courier New&#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;"><span style="color:#008000;">/// &lt;summary&gt;</span></pre>
<pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &#39;Courier New&#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;border-bottom-style:none;"><span style="color:#008000;">/// Prefix a file name with the current date time</span></pre>
<pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &#39;Courier New&#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;"><span style="color:#008000;">/// &lt;/summary&gt;</span></pre>
<pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &#39;Courier New&#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;border-bottom-style:none;"><span style="color:#008000;">/// &lt;param name=&quot;fileName&quot;&gt;The original file name&lt;/param&gt;</span></pre>
<pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &#39;Courier New&#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;"><span style="color:#008000;">/// &lt;returns&gt;A file name prefixed with the date time (e.g. 2008010101010101_test.docx)&lt;/returns&gt;</span></pre>
<pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &#39;Courier New&#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;border-bottom-style:none;"><span style="color:#0000ff;">private</span> <span style="color:#0000ff;">string</span> GetFileNameWithDate(<span style="color:#0000ff;">string</span> fileName)</pre>
<pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &#39;Courier New&#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;">{</pre>
<pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &#39;Courier New&#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;border-bottom-style:none;">&#160;</pre>
<pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &#39;Courier New&#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;">    DateTime now = DateTime.Now;</pre>
<pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &#39;Courier New&#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;border-bottom-style:none;">&#160;</pre>
<pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &#39;Courier New&#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;">    <span style="color:#0000ff;">return</span> </pre>
<pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &#39;Courier New&#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;border-bottom-style:none;">        now.Year.ToString() + </pre>
<pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &#39;Courier New&#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;">        now.Month.ToString().PadLeft(2, <span style="color:#006080;">&#39;0&#39;</span>) + </pre>
<pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &#39;Courier New&#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;border-bottom-style:none;">        now.Day.ToString().PadLeft(2, <span style="color:#006080;">&#39;0&#39;</span>) + </pre>
<pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &#39;Courier New&#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;">        now.Hour.ToString().PadLeft(2, <span style="color:#006080;">&#39;0&#39;</span>) + </pre>
<pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &#39;Courier New&#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;border-bottom-style:none;">        now.Minute.ToString().PadLeft(2, <span style="color:#006080;">&#39;0&#39;</span>) + </pre>
<pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &#39;Courier New&#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;">        now.Second.ToString().PadLeft(2, <span style="color:#006080;">&#39;0&#39;</span>) + </pre>
<pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &#39;Courier New&#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;border-bottom-style:none;">        now.Millisecond.ToString().PadLeft(2, <span style="color:#006080;">&#39;0&#39;</span>) + </pre>
<pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &#39;Courier New&#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;">        <span style="color:#006080;">&quot;_&quot;</span> + fileName;</pre>
<pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &#39;Courier New&#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;border-bottom-style:none;">&#160;</pre>
<pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &#39;Courier New&#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;">}</pre>
<pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &#39;Courier New&#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;border-bottom-style:none;">&#160;</pre>
<pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &#39;Courier New&#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;">    }</pre>
</p></div>
</div>
<p>This had another benefit, in that it made the attachment file names pretty much unique. Unlike documents in doc libraries, new attachments with the same file name as an existing attachment will not override the original, and the user will see an error message from SharePoint when trying to upload the attachment. This gets around that unfriendly experience.</p>
<p>To register my attachment, I used Gary Lapointe&#39;s custom stsadm command, <a href="http://stsadm.blogspot.com/2008/09/adding-event-receivers-using-stsadm.html" target="_blank">AddEventReceiver</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://vspug.com/toth/2008/12/18/event-handler-for-renaming-list-item-attachments/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Switch Views when InfoPath Form is Opened</title>
		<link>http://vspug.com/toth/2008/09/16/switch-views-when-infopath-form-is-opened/</link>
		<comments>http://vspug.com/toth/2008/09/16/switch-views-when-infopath-form-is-opened/#comments</comments>
		<pubDate>Tue, 16 Sep 2008 22:51:39 +0000</pubDate>
		<dc:creator>adamtoth</dc:creator>
		
		<guid isPermaLink="false"></guid>
		<description><![CDATA[I designed a form for a client that had several different views, and I needed a way to display a specific view when the form was opened. This was easy, but took me a bit to figure out.

Go to Tools &#62; Form Options.
Click the Open and Save option.
Click the Rules button, and add rules and [...]]]></description>
			<content:encoded><![CDATA[<p>I designed a form for a client that had several different views, and I needed a way to display a specific view when the form was opened. This was easy, but took me a bit to figure out.</p>
<ol>
<li>Go to <strong>Tools &gt; Form Options</strong>.</li>
<li>Click the <strong>Open and Save</strong> option.</li>
<li>Click the <strong>Rules</strong> button, and add rules and actions to switch views.</li>
</ol>
<p>With this method, I was able to set a field on form submittal to indicate which view was last active. When the submitted form was re-opened, I was able to use a conditional rule to switch to that last active view.</p>
]]></content:encoded>
			<wfw:commentRss>http://vspug.com/toth/2008/09/16/switch-views-when-infopath-form-is-opened/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Make InfoPath Contact Selector Required in Browser-Enabled Forms</title>
		<link>http://vspug.com/toth/2008/09/16/make-infopath-contact-selector-required-in-browser-enabled-forms/</link>
		<comments>http://vspug.com/toth/2008/09/16/make-infopath-contact-selector-required-in-browser-enabled-forms/#comments</comments>
		<pubDate>Tue, 16 Sep 2008 22:38:00 +0000</pubDate>
		<dc:creator>adamtoth</dc:creator>
		
		<guid isPermaLink="false"></guid>
		<description><![CDATA[If you&#39;ve used the InfoPath Contact Selector before, you might have seen that it does not support validation like other InfoPath controls do. There is no option on the Properties dialog for the control to make it a required field. To work around this, I used a combination of rules and conditional formatting to prevent [...]]]></description>
			<content:encoded><![CDATA[<p>If you&#39;ve used the InfoPath Contact Selector before, you might have seen that it does not support validation like other InfoPath controls do. There is no option on the Properties dialog for the control to make it a required field. To work around this, I used a combination of rules and conditional formatting to prevent the form from being submitted if the control does not have a value. </p>
<p>The easiest way to do this is to create conditional rules in the Submit Options dialog:</p>
<ol>
<li>Configure your form and add a Contact Selector control (<a href="http://msdn.microsoft.com/en-us/library/ms558892.aspx" target="_blank">see this article for instructions</a>).</li>
<li>Go to <b>Tools &gt; Submit Options</b>.</li>
<li>Make sure that <b>Allow Users to Submit this Form</b> is checked.</li>
<li>Click the option to <b>Perform custom action using rules</b>.</li>
<li>Click the <b>Rules&#8230;</b> button.</li>
<li>In the Rules dialog, click the <b>Add&#8230;</b> button.</li>
<li>In the Rule dialog, click the <b>Set Condition&#8230;</b> button.</li>
<li>In the Condition dialog, pull down the first dropdown, choose <b>Select a field or group&#8230;</b>, and drill down and choose the <b>DisplayName</b> field from your data connection. Select i<b>s blank</b> in the second dropdown.</li>
<li>Click the <b>And&gt;</b> button to add a second condition.</li>
<li>In the last dropdown on the first condition, change it from <b>And</b> to <b>Or</b>.</li>
<li>In the second condition, select the <b>DisplayName</b> field again, and choose <b>is not present</b> for the condition. Your two conditions should look like this:            </li>
<div class="wlWriterSmartContent" id="scid:51CF81A4-8F44-4a2c-8837-198C090B9994:8c5c7a5c-1165-4377-9310-5424cd2644f1" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;">
<p><img style="border-right:2px;border-top:2px;border-left:2px;border-bottom:2px;" src="http://lh5.ggpht.com/adam.toth/SNAw0BKwCxI/AAAAAAAAAEE/jtmA5uzot_0/s400/contactselectorconditions.jpg" height="97" width="400" alt="  " /></p>
</div>
<li>Click <b>OK</b>. In the Rule dialog, do not add any Actions. Check the box to <b>Stop processing rules when this rule finishes</b>.</li>
<li>Make sure that this rule appears first in the list of Rules.</li>
</ol>
<p>The only downside to this approach is that there is no visual to the user, since InfoPath Forms Services does not support showing a dialog message. The form will just not do anything. To get an even better user experience, You can hide the Submit option from the Toolbar, and use your own Submit buttons with Conditional Formatting:</p>
<ol>
<li>Drag a button on the page.</li>
<li>Right-click and choose <b>Conditional Formatting&#8230;</b>.</li>
<li>Click <b>Add&#8230;</b> to add conditions.</li>
<li>In the Condition dialog, add the two conditions in steps 8-11 above, and choose Disable this Control.           </li>
<div class="wlWriterSmartContent" id="scid:51CF81A4-8F44-4a2c-8837-198C090B9994:fb2425c7-c2d8-4b96-9c13-535fecc99f58" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;">
<p><img style="border-right:2px;border-top:2px;border-left:2px;border-bottom:2px;" src="http://lh5.ggpht.com/adam.toth/SNAzu4N5XwI/AAAAAAAAAEI/hMjaDPoYJSk/s400/contactselectorconditionalformatting.jpg" height="206" width="400" alt="  " /></p>
</div>
</ol>
<p>&nbsp;</p>
<p>Now, your submit button will be disabled until the user picks a person.   </p>
]]></content:encoded>
			<wfw:commentRss>http://vspug.com/toth/2008/09/16/make-infopath-contact-selector-required-in-browser-enabled-forms/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>My SharePoint Sites Links Missing &#8211; Fix</title>
		<link>http://vspug.com/toth/2008/08/26/my-sharepoint-sites-links-missing-fix/</link>
		<comments>http://vspug.com/toth/2008/08/26/my-sharepoint-sites-links-missing-fix/#comments</comments>
		<pubDate>Tue, 26 Aug 2008 22:26:51 +0000</pubDate>
		<dc:creator>adamtoth</dc:creator>
		
		<guid isPermaLink="false"></guid>
		<description><![CDATA[One client had a problem with profile and membership synchronization, and the &#34;My SharePoint Sites&#34; links would not appear for anyone. This also affected the &#34;SharePoint Sites&#34; and &#34;Membership&#34; web parts on users&#39; MySites &#8211; no SharePoint related links would show up in these parts.
We verified that users were explicitly added into the &#34;Members&#34; group [...]]]></description>
			<content:encoded><![CDATA[<p>One client had a problem with profile and membership synchronization, and the &quot;My SharePoint Sites&quot; links would not appear for anyone. This also affected the &quot;SharePoint Sites&quot; and &quot;Membership&quot; web parts on users&#39; MySites &#8211; no SharePoint related links would show up in these parts.</p>
<p>We verified that users were explicitly added into the &quot;Members&quot; group of SharePoint sites, we performed full crawls and ran all the timer jobs. Still no dice.</p>
<p>Eventually, a support ticket with MS revealed that having the Content Database set to Offline prevented that functionality from working. </p>
]]></content:encoded>
			<wfw:commentRss>http://vspug.com/toth/2008/08/26/my-sharepoint-sites-links-missing-fix/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
