<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" version="2.0"><channel><atom:id>tag:blogger.com,1999:blog-7384653670825187633</atom:id><lastBuildDate>Thu, 16 Feb 2012 13:08:34 +0000</lastBuildDate><title>Ivan on Software</title><description>Thoughts and ideas on SharePoint and .NET development</description><link>http://neganov.blogspot.com/</link><managingEditor>noreply@blogger.com (Ivan Neganov)</managingEditor><generator>Blogger</generator><openSearch:totalResults>37</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/IvanOnSoftware" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="ivanonsoftware" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7384653670825187633.post-173879727702930967</guid><pubDate>Sun, 28 Aug 2011 16:17:00 +0000</pubDate><atom:updated>2011-08-28T11:23:53.621-07:00</atom:updated><title>Custom Alerts in SharePoint - Templates or Code?</title><description>&lt;p&gt;My client needed a customized alert created each time a new issue was added to a standard Issues list. The only difference from out-of-the-box alert functionality was that customized alert Email message needed to have an Issue ID in its subject. I haven’t customized alerts before so I did some research, which showed that: &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;you can customize HTML of an alert through alert templates and use placeholders to insert values in an Email message. &lt;/li&gt;    &lt;li&gt;there is an API letting you to tap into alert message processing pipeline and customize Email message before it is sent out. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;There is a lot of information online on the subject, yet I still had difficulties with this seemingly easy problem. The following resources were most useful to me: MSDN (&lt;a title="http://msdn.microsoft.com/en-us/library/bb802949.aspx" href="http://msdn.microsoft.com/en-us/library/bb802949.aspx"&gt;http://msdn.microsoft.com/en-us/library/bb802949.aspx&lt;/a&gt;), &lt;a title="Customizing Alert Notifications and Alert Templates in Windows SharePoint Services 3.0" href="http://blogs.msdn.com/b/sharepointdeveloperdocs/archive/2007/12/07/customizing-alert-notifications-and-alert-templates-in-windows-sharepoint-services-3-0.aspx" target="_blank"&gt;Albert Meerscheidt’s post about alerts in WSS 3.0&lt;/a&gt; and &lt;a title="Creating custom list alert templates in SharePoint 2010" href="http://www.sharemuch.com/2010/08/15/creating-custom-list-alert-templates-in-sharepoint-2010/" target="_blank"&gt;Yaroslav Pentsarskyy’s post about customizing alerts in SharePoint 2010&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;For me empowered with this information the task came down to writing a correct alert template, or so I thought. Take a look at this fragment of an out-of-the-box immediate alert template defining Email message subject text (immediate alerts are sent right away while digest alerts are sent later as a summary):&lt;/p&gt;&lt;span class="Apple-style-span"&gt;&amp;lt;Subject&amp;gt;
&lt;br /&gt;  &amp;lt;GetVar Name="AlertTitle" /&amp;gt;
&lt;br /&gt;  &amp;lt;HTML&amp;gt;&amp;lt;![CDATA[ - ]]&amp;gt;&amp;lt;/HTML&amp;gt;
&lt;br /&gt;  &amp;lt;GetVar Name="ItemName" /&amp;gt;
&lt;br /&gt;&amp;lt;/Subject&amp;gt;&lt;/span&gt;
&lt;br /&gt;
&lt;br /&gt;The interesting part here is placeholders “AlertTitle” and “ItemName” and the way they are used. I have a field named “ID” (it is a part of a standard Issues list), and a naive approach of writing &lt;span&gt;&amp;lt;GetVar Name=”ID” /&amp;gt;&lt;/span&gt; didn’t get me anywhere. Same result with adding a custom text column named “ATextColumn” and then doing &lt;span&gt;&amp;lt;GetVar Name=”ATextColumn” /&amp;gt;&lt;/span&gt;. Well, the &lt;span&gt;&amp;lt;GetVar&amp;gt;&lt;/span&gt; element is a part of &lt;a title="GetVar Element (View)" href="http://msdn.microsoft.com/en-us/library/ms429081.aspx" target="_blank"&gt;CAML Vew Schema&lt;/a&gt; and yields a value of a local or a global variable set in current page context, but what are these placeholders and how are they set? At this point I have realized that my effort estimates were a little too optimistic. Then I bumped into a &lt;a title="Managing Alerts" href="http://isle.paisley.ac.uk/_vti_bin/HELP/1033/SPS/HTML/stsf13.htm" target="_blank"&gt;help article about alerts in WSS 2.0&lt;/a&gt;. Among other things it had a list of “tags” that could be included in alert templates. Here it is:
&lt;br /&gt;
&lt;br /&gt;&lt;table border="1" cellspacing="0" cellpadding="2" width="750"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td valign="top" width="205"&gt;&lt;b&gt;Tag&lt;/b&gt;&lt;/td&gt;&lt;td valign="top" width="727"&gt;&lt;b&gt;Description&lt;/b&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td valign="top" width="209"&gt;SiteUrl&lt;/td&gt;&lt;td valign="top" width="724"&gt;The full URL to the site.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td valign="top" width="212"&gt;SiteName&lt;/td&gt;&lt;td valign="top" width="721"&gt;The name of the site.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td valign="top" width="215"&gt;SiteLanguage&lt;/td&gt;&lt;td valign="top" width="719"&gt;The &lt;a href="http://isle.paisley.ac.uk/spsglos.htm"&gt;locale ID (LCID)&lt;/a&gt; for the language used in the site.
&lt;br /&gt;For example, 1033 for U.S. English.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td valign="top" width="217"&gt;AlertFrequency&lt;/td&gt;&lt;td valign="top" width="717"&gt;Immediate (0), Daily (1), or Weekly (2).&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td valign="top" width="219"&gt;ListUrl&lt;/td&gt;&lt;td valign="top" width="715"&gt;The full URL to the list.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td valign="top" width="221"&gt;ListName&lt;/td&gt;&lt;td valign="top" width="714"&gt;The name of the list.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td valign="top" width="222"&gt;ItemUrl&lt;/td&gt;&lt;td valign="top" width="713"&gt;The full URL to the item.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td valign="top" width="223"&gt;ItemName&lt;/td&gt;&lt;td valign="top" width="712"&gt;The name of the item.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td valign="top" width="224"&gt;EventType&lt;/td&gt;&lt;td valign="top" width="711"&gt;ItemAdded (1), Item Modified (2), Item Deleted (4), DiscussionAdded (16),
&lt;br /&gt;Discussion Modified (32), Discussion Deleted (64), Discussion Closed (128),
&lt;br /&gt;Discussion Activated (256).&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td valign="top" width="225"&gt;ModifiedBy&lt;/td&gt;&lt;td valign="top" width="711"&gt;The name of the user who modified an item.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td valign="top" width="225"&gt;TimeLastModified&lt;/td&gt;&lt;td valign="top" width="711"&gt;The time the item was last modified.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td valign="top" width="225"&gt;MySubsUrl&lt;/td&gt;&lt;td valign="top" width="711"&gt;The full URL to the My Alerts on this Site page in &lt;b&gt;Site Settings&lt;/b&gt;.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
&lt;br /&gt;Some of these tags are used in the out-of-the-box templates. I tried the rest of them and all have worked. So it appears as we are limited to using these 12 tags only, and that it is an old functionality which survived WSS 2.0, WSS 3.0 and SharePoint Foundation 2010 releases. If someone knows more about it please post a comment to validate, disprove or complete this statement.
&lt;br /&gt;
&lt;br /&gt;&lt;div&gt;Another thing that comes out of reflecting over template XML is usage of &lt;span&gt;&amp;lt;GetVar Name=”OldValue#{Field}” /&amp;gt;&lt;/span&gt; or &lt;span&gt;&amp;lt;GetVar Name=”NewValue#{Field}” /&amp;gt;&lt;/span&gt; or&lt;span&gt; &amp;lt;GetVar Name=”DisplayName#{Field}” /&amp;gt;&lt;/span&gt;. These elements are descendents of &lt;a title="Fields Element (Alert Templates)" href="http://msdn.microsoft.com/en-us/library/ff407228.aspx" target="_blank"&gt;&lt;span&gt;&amp;lt;Fields&amp;gt;&lt;/span&gt;&lt;/a&gt; element for immediate alerts, and of &lt;a title="RowFields Element (Alert Templates)" href="http://msdn.microsoft.com/en-us/library/ff408269.aspx" target="_blank"&gt;&amp;lt;RowFields&amp;gt;&lt;/a&gt; element for digest alerts. If you inspect generated alert body HTML then you would notice that fields (or columns) are iterated over and their values are inserted in the body except when a field is listed inside of&lt;span&gt; &lt;/span&gt;&lt;a title="ImmediateNotificationExcludedFields (Alert Templates)" href="http://msdn.microsoft.com/en-us/library/ff408063.aspx" target="_blank"&gt;&lt;span&gt;&amp;lt;ImmediateNotificationExcludedFields&amp;gt;&lt;/span&gt;&lt;/a&gt; or &lt;a title="DigestNotificationExcludedFields Element (Alert Templates)" href="http://msdn.microsoft.com/en-us/library/ff407637.aspx" target="_blank"&gt;&lt;span&gt;&amp;lt;DigestNotificationExcludedFields&amp;gt;&lt;/span&gt;&lt;/a&gt; elements. So then &lt;span&gt;&amp;lt;Fields&amp;gt;&lt;/span&gt; element establishes a loop, and the &lt;span&gt;{Field}&lt;/span&gt; must be a contextual variable inside this loop. With the above syntax you can get display name, old or new values for each field into the Email body and exclude fields you don’t want to be listed.
&lt;br /&gt;
&lt;br /&gt;Great, but how do I get the ID into my Email’s subject? I don’t want to list a bunch of fields in my subject, just the ID, so I don’t want to use &lt;span&gt;&amp;lt;Fields&amp;gt;&lt;/span&gt; element there. The API did the trick. I have created a class implementing &lt;a title="IAlertNotifyHandler Interface" href="http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.ialertnotifyhandler.aspx" target="_blank"&gt;&lt;span&gt;IAlertNotifyHandler&lt;/span&gt;&lt;/a&gt; interface and used regular expressions to replace a placeholder with a value:&lt;/div&gt;&lt;div&gt;
&lt;br /&gt;&lt;pre class="csharpcode" style="line-height:70%"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; MessageCustomizer : IAlertNotifyHandler
&lt;br /&gt;{
&lt;br /&gt;  &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;bool&lt;/span&gt; OnNotification(SPAlertHandlerParams parameters)
&lt;br /&gt;  {
&lt;br /&gt;      &lt;span class="kwrd"&gt;string&lt;/span&gt; webUrl = parameters.siteUrl + parameters.webUrl;
&lt;br /&gt;
&lt;br /&gt;      &lt;span class="kwrd"&gt;using&lt;/span&gt; (SPSite site = &lt;span class="kwrd"&gt;new&lt;/span&gt; SPSite(webUrl))
&lt;br /&gt;      &lt;span class="kwrd"&gt;using&lt;/span&gt;(SPWeb web = site.OpenWeb())
&lt;br /&gt;      {
&lt;br /&gt;          &lt;span class="kwrd"&gt;string&lt;/span&gt; to = parameters.headers[&lt;span class="str"&gt;"To"&lt;/span&gt;];
&lt;br /&gt;          &lt;span class="kwrd"&gt;string&lt;/span&gt; subjectTemplate = parameters.headers[&lt;span class="str"&gt;"Subject"&lt;/span&gt;];
&lt;br /&gt;          &lt;span class="kwrd"&gt;string&lt;/span&gt; itemId = parameters.eventData[0].itemId.ToString();
&lt;br /&gt;
&lt;br /&gt;          &lt;span class="rem"&gt;//&lt;/span&gt;
&lt;br /&gt;          &lt;span class="rem"&gt;// Below we are replacing a placeholder we have &lt;/span&gt;
&lt;br /&gt;          &lt;span class="rem"&gt;// created in our alert template with the actual value.&lt;/span&gt;
&lt;br /&gt;          &lt;span class="rem"&gt;//&lt;/span&gt;
&lt;br /&gt;
&lt;br /&gt;          &lt;span class="kwrd"&gt;string&lt;/span&gt; subject = Regex.Replace(
&lt;br /&gt;              subjectTemplate,
&lt;br /&gt;              &lt;span class="str"&gt;"#ID#"&lt;/span&gt;,
&lt;br /&gt;              itemId,
&lt;br /&gt;              RegexOptions.IgnoreCase);
&lt;br /&gt;          &lt;span class="kwrd"&gt;bool&lt;/span&gt; result = SPUtility.SendEmail(
&lt;br /&gt;              web,
&lt;br /&gt;              &lt;span class="kwrd"&gt;false&lt;/span&gt;,
&lt;br /&gt;              &lt;span class="kwrd"&gt;false&lt;/span&gt;,
&lt;br /&gt;              to,
&lt;br /&gt;              subject,
&lt;br /&gt;              parameters.body);
&lt;br /&gt;          &lt;span class="kwrd"&gt;return&lt;/span&gt; result;
&lt;br /&gt;      }
&lt;br /&gt;  }
&lt;br /&gt;}&lt;/pre&gt;
&lt;br /&gt;&lt;style type="text/css"&gt;&lt;br /&gt;.csharpcode, .csharpcode pre&lt;br /&gt;{&lt;br /&gt;	font-size: small;&lt;br /&gt;	color: black;&lt;br /&gt;	font-family: consolas, "Courier New", courier, monospace;&lt;br /&gt;	background-color: #ffffff;&lt;br /&gt;	/*white-space: pre;*/&lt;br /&gt;}&lt;br /&gt;.csharpcode pre { margin: 0em; }&lt;br /&gt;.csharpcode .rem { color: #008000; }&lt;br /&gt;.csharpcode .kwrd { color: #0000ff; }&lt;br /&gt;.csharpcode .str { color: #006080; }&lt;br /&gt;.csharpcode .op { color: #0000c0; }&lt;br /&gt;.csharpcode .preproc { color: #cc6633; }&lt;br /&gt;.csharpcode .asp { background-color: #ffff00; }&lt;br /&gt;.csharpcode .html { color: #800000; }&lt;br /&gt;.csharpcode .attr { color: #ff0000; }&lt;br /&gt;.csharpcode .alt &lt;br /&gt;{&lt;br /&gt;	background-color: #f4f4f4;&lt;br /&gt;	width: 100%;&lt;br /&gt;	margin: 0em;&lt;br /&gt;}&lt;br /&gt;.csharpcode .lnum { color: #606060; }&lt;/style&gt;We still need a customized alert template – firstly to insert our own custom placeholder (in my example #ID#) and secondly to register the &lt;span&gt;MessageCustomizer&lt;/span&gt; class so its &lt;span&gt;OnNotification()&lt;/span&gt; method would get called. Here is updated fragment defining Email’s subject:
&lt;br /&gt;
&lt;br /&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Subject&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;br /&gt;  &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;HTML&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&amp;lt;!&lt;/span&gt;[CDATA[Issue ID #ID#: ]]&lt;span class="kwrd"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;HTML&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;br /&gt;  &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;GetVar&lt;/span&gt; &lt;span class="attr"&gt;Name&lt;/span&gt;&lt;span class="kwrd"&gt;="AlertTitle"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
&lt;br /&gt;  &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;HTML&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&amp;lt;!&lt;/span&gt;[CDATA[ - ]]&lt;span class="kwrd"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;HTML&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;br /&gt;  &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;GetVar&lt;/span&gt; &lt;span class="attr"&gt;Name&lt;/span&gt;&lt;span class="kwrd"&gt;="ItemName"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
&lt;br /&gt;&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;Subject&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;br /&gt;
&lt;br /&gt;Registration of &lt;span&gt;MessageCustomizer&lt;/span&gt; class and its assembly is done inside of &lt;a title="NotificationHandlerClassName Element" href="http://msdn.microsoft.com/en-us/library/ff407449.aspx" target="_blank"&gt;&amp;lt;NotificationHandlerClassName&amp;gt;&lt;/a&gt; and &lt;a title="NotificationHandlerAssembly Element" href="http://msdn.microsoft.com/en-us/library/ff407215.aspx" target="_blank"&gt;&amp;lt;NotificationHandlerAssembly&amp;gt;&lt;/a&gt; elements of the template:
&lt;br /&gt;
&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: monospace; font-size: 13px; white-space: pre; "&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;NotificationHandlerAssembly&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;AlertCustomization, Version=1.0.0.0, Culture=neutral, PublicKeyToken=bda7bcef852778f0&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;NotificationHandlerAssembly&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;NotificationHandlerClassName&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;AlertCustomization.MessageCustomizer&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;NotificationHandlerClassName&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;style type="text/css"&gt;&lt;br /&gt;.csharpcode, .csharpcode pre&lt;br /&gt;{&lt;br /&gt;	font-size: small;&lt;br /&gt;	color: black;&lt;br /&gt;	font-family: consolas, "Courier New", courier, monospace;&lt;br /&gt;	background-color: #ffffff;&lt;br /&gt;	/*white-space: pre;*/&lt;br /&gt;}&lt;br /&gt;.csharpcode pre { margin: 0em; }&lt;br /&gt;.csharpcode .rem { color: #008000; }&lt;br /&gt;.csharpcode .kwrd { color: #0000ff; }&lt;br /&gt;.csharpcode .str { color: #006080; }&lt;br /&gt;.csharpcode .op { color: #0000c0; }&lt;br /&gt;.csharpcode .preproc { color: #cc6633; }&lt;br /&gt;.csharpcode .asp { background-color: #ffff00; }&lt;br /&gt;.csharpcode .html { color: #800000; }&lt;br /&gt;.csharpcode .attr { color: #ff0000; }&lt;br /&gt;.csharpcode .alt &lt;br /&gt;{&lt;br /&gt;	background-color: #f4f4f4;&lt;br /&gt;	width: 100%;&lt;br /&gt;	margin: 0em;&lt;br /&gt;}&lt;br /&gt;.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;We can now wire up the templates and the handler. Handler’s assembly needs to go to the GAC, then you copy and rename &lt;span&gt;alerttemplates.xml&lt;/span&gt; file sitting in &lt;span&gt;14\TEMPLATE\XML&lt;/span&gt; folder, add your template (or again copy an existing one and change it), then you register this file with SharePoint running&lt;span class="Apple-style-span"&gt; &lt;b&gt;stsadm –o updatealerttemplates&lt;/b&gt;&lt;/span&gt; command. I didn’t find PowerShell cmdlets equivalent to this command. Lastly you need to assign your template to a list using &lt;a title="SPList.AlertTemplate Property" href="http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.splist.alerttemplate.aspx" target="_blank"&gt;&lt;span&gt;SPList.AlertTemplate&lt;/span&gt;&lt;/a&gt; property. You can write a PowerShell script or use a feature receiver. The latter approach is demonstrated in Yaroslav Pentsarskyy’s post mentioned earlier.
&lt;br /&gt;
&lt;br /&gt;So we are arriving at a standard “It depends…” answer to the question of whether to customize alerts via templates or via code. Regardless of which approach works for you for any such customization that is not an ad hoc fix or a proof of concept you are looking into creating a package including deployment script, a SharePoint solution and possibly a feature with feature receiver. The functionality is almost identical between WSS 3.0 and SharePoint Foundation 2010 with the latter adding SMS support. Also with Visual Studio 2010 it is much easier to package things, yet you are probably still looking into a few hours of work to get it done right.  &lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7384653670825187633-173879727702930967?l=neganov.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://neganov.blogspot.com/2011/08/custom-alerts-in-sharepoint-templates.html</link><author>noreply@blogger.com (Ivan Neganov)</author><thr:total>1</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7384653670825187633.post-5820943211282341690</guid><pubDate>Wed, 13 Jul 2011 04:34:00 +0000</pubDate><atom:updated>2011-07-12T21:49:06.446-07:00</atom:updated><title>Calling WCF Web Services from a SharePoint Timer Job</title><description>&lt;p&gt;Imagine that you are building an enterprise application on top of SharePoint 2010, which is installed on a multi-server farm. The application consumes a WCF web service – custom libraries use generated proxy classes and endpoint configuration is stored inside of a web application’s web.config file. Configuration settings are applied to all servers in the farm by a script when application is provisioned. And your application needs to be deployed to development, testing and production farms, all of which have differences in how WCF endpoints and bindings are configured, including variance in WCF binding types.&lt;/p&gt;  &lt;p&gt;Now imagine that you need to call this web service from two places: from your custom web application code and from a timer job, perhaps because you need to cache results for better performance, but also be able to fall back to synchronous call when results get outdated. You will face a complication: how do you configure your WCF client when you invoke the service from a timer job? &lt;/p&gt;  &lt;p&gt;You have a few options:&lt;/p&gt;  &lt;p&gt;1. Implement a configuration file &lt;font face="Courier New"&gt;OWSTIMER.exe.config&lt;/font&gt;;&lt;/p&gt;  &lt;p&gt;2. Construct binding and endpoint objects inside of a timer job, set their properties through code then create a channel or extended &lt;font face="Courier New"&gt;ClientBase&amp;lt;T&amp;gt;&lt;/font&gt; object and execute a service method call on it.&lt;/p&gt;  &lt;p&gt;3. Load service model configuration from application’s &lt;font face="Courier New"&gt;web.config&lt;/font&gt; file and create and populate appropriate binding and endpoint objects. Then create and use a channel or a &lt;font face="Courier New"&gt;ClientBase&amp;lt;T&amp;gt;&lt;/font&gt; object to invoke the service method.&lt;/p&gt;  &lt;p&gt;Option 1 has issues with provisioning files to locations not intended for custom application files and keeping same configuration information in two locations on all farm servers.&lt;/p&gt;  &lt;p&gt;Option 2 hard-codes binding information, which makes it very difficult to maintain code and troubleshoot WCF issues in multiple environments.&lt;/p&gt;  &lt;p&gt;Option 3 is apparently the best choice since configuration is stored in one place, it can easily be changed in &lt;font face="Courier New"&gt;web.config&lt;/font&gt;, and the changes will affect WCF service client objects in both locations. So let us look at what’s involved in implementing the option 3.&lt;/p&gt;  &lt;p&gt;Before you can load a configuration object from &lt;font face="Courier New"&gt;web.config&lt;/font&gt; file you need to locate it. Here we can leverage &lt;font face="Courier New"&gt;SPIisSettings&lt;/font&gt; object, which is available for each security zone. Next you load &lt;font face="courier ne"&gt;web.config&lt;/font&gt; content by using &lt;font face="Courier New"&gt;WebConfigurationManager.OpenMappedConfiguration()&lt;/font&gt; method: &lt;/p&gt;&lt;br /&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;span style="color: #0000ff"&gt;private&lt;/span&gt; System.Configuration.Configuration GetWebConfig(SPUrlZone zone)&lt;br /&gt;{&lt;br /&gt;    SPIisSettings iisSettings = &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.WebApplication.IisSettings[zone];&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; rootPath = iisSettings.Path.ToString();&lt;br /&gt;    WebConfigurationFileMap map = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; WebConfigurationFileMap();&lt;br /&gt;    map.VirtualDirectories.Add(&lt;br /&gt;        &lt;span style="color: #006080"&gt;&amp;quot;/&amp;quot;&lt;/span&gt;,&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; VirtualDirectoryMapping(rootPath, &lt;span style="color: #0000ff"&gt;true&lt;/span&gt;));&lt;br /&gt;    System.Configuration.Configuration webConfig =&lt;br /&gt;        WebConfigurationManager.OpenMappedWebConfiguration(&lt;br /&gt;        map,&lt;br /&gt;        &lt;span style="color: #006080"&gt;&amp;quot;/web.config&amp;quot;&lt;/span&gt;);&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; webConfig;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div&gt;Once you have obtained configuration object, you need to infer type of binding from service model configuration, and apply all attributes to it, as well as create an endpoint. Given names of a binding and an endpoint you find corresponding &lt;font face="Courier New"&gt;BindingCollectionElement&lt;/font&gt; and &lt;font face="Courier New"&gt;ChannelEndpointElement&lt;/font&gt;. The actual binding object is created using .NET Reflection and value of &lt;font face="Courier New"&gt;BindingCollectionElement.BindingType&lt;/font&gt; property:&lt;/div&gt;&lt;div id="codeSnippetWrapper"&gt;&lt;br /&gt;  &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;span style="color: #0000ff"&gt;private&lt;/span&gt; MyServiceClient MakeMyServiceClient(&lt;br /&gt;    System.Configuration.Configuration config)&lt;br /&gt;{&lt;br /&gt;    &lt;span style="color: #008000"&gt;//&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #008000"&gt;// Get endpoint and binding names from settings.&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #008000"&gt;//&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; bindingName = GetValue(&lt;span style="color: #006080"&gt;&amp;quot;Key_MyBindingName&amp;quot;&lt;/span&gt;);&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; endpointName = GetValue(&lt;span style="color: #006080"&gt;&amp;quot;Key_MyEndpointName&amp;quot;&lt;/span&gt;);&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #008000"&gt;//&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #008000"&gt;// Determine endpoint and binding elements used.&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #008000"&gt;//&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    var sectionGroup = ServiceModelSectionGroup.&lt;br /&gt;        GetSectionGroup(config);&lt;br /&gt;    ChannelEndpointElement endpointElement = &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;for&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = 0; i &amp;lt; sectionGroup.Client.Endpoints.Count; ++i)&lt;br /&gt;    {&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (sectionGroup.Client.Endpoints[i].Name == endpointName)&lt;br /&gt;        {&lt;br /&gt;            endpointElement = sectionGroup.Client.Endpoints[i];&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;break&lt;/span&gt;;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    BindingCollectionElement collectionElement = sectionGroup.&lt;br /&gt;        Bindings.BindingCollections.Find(&lt;br /&gt;            item =&amp;gt; item.BindingName == endpointElement.Binding);&lt;br /&gt;    IBindingConfigurationElement bindingConfig = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt;&lt;br /&gt;        List&amp;lt;IBindingConfigurationElement&amp;gt;(&lt;br /&gt;            collectionElement.ConfiguredBindings).Find(item =&amp;gt;&lt;br /&gt;                item.Name == endpointElement.BindingConfiguration);&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #008000"&gt;//&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #008000"&gt;// Create address and binding of proper type and populate them.&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #008000"&gt;//&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    Binding binding = (Binding)collectionElement.BindingType.&lt;br /&gt;        GetConstructor(&lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Type[0]).Invoke(&lt;span style="color: #0000ff"&gt;new&lt;/span&gt; &lt;span style="color: #0000ff"&gt;object&lt;/span&gt;[0]);&lt;br /&gt;    bindingConfig.ApplyConfiguration(binding);&lt;br /&gt;    EndpointAddress address = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; EndpointAddress(&lt;br /&gt;        endpointElement.Address);&lt;br /&gt;&lt;br /&gt;    MyServiceClient client = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; MyServiceClient(binding, address);&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; client;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;That’s it. The credit for &lt;font face="Courier New"&gt;MakeMyServiceClient()&lt;/font&gt; method goes to Microsoft. When I was searching for examples of inferring binding type and properties from configuration I bumped into implementation of a read-only property named &lt;font face="Courier New"&gt;Binding&lt;/font&gt; on an internal type &lt;font face="Courier New"&gt;Microsoft.SharePoint.Administration.Claims.SPSecurityTokenServiceApplication&lt;/font&gt; inside of &lt;font face="Courier New"&gt;Microsoft.SharePoint&lt;/font&gt; assembly. I have reused that code with minor deviations in the example above. Open up Reflector and take a look at that property.&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7384653670825187633-5820943211282341690?l=neganov.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://neganov.blogspot.com/2011/07/calling-wcf-web-services-from.html</link><author>noreply@blogger.com (Ivan Neganov)</author><thr:total>2</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7384653670825187633.post-7652772969021245369</guid><pubDate>Thu, 14 Apr 2011 03:47:00 +0000</pubDate><atom:updated>2011-04-14T06:02:04.131-07:00</atom:updated><title>Property Bag in Application Setting Manager Does Not Find a Key… Easily</title><description>&lt;p&gt;I am working on a custom SharePoint 2010 application now, which relies on &lt;a title="Developing Applications for SharePoint 2010" href="http://207.46.16.248/en-us/library/ff770300.aspx" target="_blank"&gt;Microsoft SharePoint 2010 Guidance for developers&lt;/a&gt;. Today I came across an interesting issue while utilizing Application Setting Manager component of the guidance library. I thought I’ve set up my application according to &lt;a title="Using the Application Setting Manager Interfaces" href="http://207.46.16.248/en-us/library/ff798443.aspx" target="_blank"&gt;the instructions&lt;/a&gt;, but I could not get settings retrieved. It turned out that there is a nuance that was not obvious from documentation, which I’d like to point out. &lt;/p&gt;  &lt;p&gt;So the setting manager stores configuration settings in a property bag of a web site, site collection, web application or a farm. It can be hierarchical, or you can specify level at which you want to store a setting. Quite powerful. In my case I used a site collection scoped feature to deploy my settings and store them in a site collection property bag. Here is a simplified fragment of my feature receiver class provisioning application settings:&lt;/p&gt;  &lt;div&gt;   &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; height: 184px; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;var site = properties.Feature.Parent &lt;span style="color: #0000ff"&gt;as&lt;/span&gt; SPSite;&lt;br /&gt;var locator = SharePointServiceLocator.GetCurrent();&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #008000"&gt;// Acquire instances of config manager and property bag&lt;/span&gt;&lt;br /&gt;var configManager = locator.GetInstance&amp;lt;IConfigManager&amp;gt;();&lt;br /&gt;configManager.SetWeb(site.RootWeb);&lt;br /&gt;var bag = configManager.GetPropertyBag(ConfigLevel.CurrentSPSite);&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #008000"&gt;// Provision application settings&lt;/span&gt;&lt;br /&gt;configManager.SetInPropertyBag(&lt;span style="color: #006080"&gt;&amp;quot;Key1&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;Value1&amp;quot;&lt;/span&gt;, bag);&lt;br /&gt;configManager.SetInPropertyBag(&lt;span style="color: #006080"&gt;&amp;quot;Key2&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;Value2&amp;quot;&lt;/span&gt;, bag);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To retrieve the settings I used the following logic:&lt;/div&gt;&lt;div id="codeSnippetWrapper"&gt;&lt;br /&gt;  &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;var locator = SharePointServiceLocator.GetCurrent();&lt;br /&gt;var config = locator.GetInstance&amp;lt;IConfigManager&amp;gt;();&lt;br /&gt;var bag = config.GetPropertyBag(ConfigLevel.CurrentSPSite);&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (!bag.Contains(key))&lt;br /&gt;{&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;throw&lt;/span&gt; &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; MyKeyNotFoundException();&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;I would be not finding the key and getting an exception. My problem was in just relying on the intellisense – why not? Well, the Microsoft guidance had it right though: in the examples&amp;#160; the check is made as follows:&lt;/div&gt;&lt;div id="codeSnippetWrapper"&gt;&lt;br /&gt;  &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (!config.ContainsKeyInPropertyBag(key, bag))&lt;br /&gt;{&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;throw&lt;/span&gt; &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; MyKeyNotFoundException();&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;And this one works fine.&amp;#160; You can check quite easily what is in your site’s property bag; this and availability of the source code of Microsoft.Practices.SharePoint.Common library help to understand what is going on. Here is how you can see your site collection’s property bag contents using PowerShell (it is stored in the root web of the site collection):&lt;/div&gt;&lt;div id="codeSnippetWrapper"&gt;&lt;br /&gt;  &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;$web = Get-SPWeb http:&lt;span style="color: #008000"&gt;//yoursitecollectionaddress/&lt;/span&gt;&lt;br /&gt;$web.AllProperties | fl&lt;/pre&gt;&lt;br /&gt;You will find that your keys are in the form &lt;strong&gt;PnP.Config.Key.&lt;/strong&gt;Key1&lt;strong&gt;._Site_ &lt;/strong&gt;where the highlighted parts are attached to your actual key. The prefix is a constant, the suffix depends on a property bag type you use. Now if you try calling original method &lt;font face="Courier New"&gt;bag.Contains(key) &lt;/font&gt;passing it &lt;strong&gt;PnP.Config.Key.Key1&lt;/strong&gt; – then it will find the key!&lt;/div&gt;&lt;p&gt;One other observation, – you are probably using &lt;a title="SharePoint Service Locator" href="http://207.46.16.248/en-us/library/ff798484.aspx" target="_blank"&gt;SharePoint Service Locator&lt;/a&gt; pattern with the setting manager, and like I do have unit tests. I needed to replace implementation of &lt;font face="Courier New"&gt;IConfigManager&lt;/font&gt; and &lt;font face="Courier New"&gt;IPropertyBag&lt;/font&gt; interfaces with mock classes. Without knowing about this “feature” my mock implementation would find a value for the key as follows: &lt;font face="Courier New"&gt;bag.Contains(“Key1”) == true&lt;/font&gt;, which would add confusion when the same key would not work in a web site. So try to always use &lt;font face="Courier New"&gt;config.ContainsInPropertyBag(key, bag) &lt;/font&gt;method instead.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7384653670825187633-7652772969021245369?l=neganov.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://neganov.blogspot.com/2011/04/property-bag-in-application-setting.html</link><author>noreply@blogger.com (Ivan Neganov)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7384653670825187633.post-5813168160561710535</guid><pubDate>Sat, 29 Jan 2011 19:46:00 +0000</pubDate><atom:updated>2011-01-29T11:54:26.476-08:00</atom:updated><title>Extending CoreResultsWebPart to Handle Search Queries Written in FAST Query Language</title><description>&lt;p&gt;This was one of &lt;a title="October 19 MSPUG meeting" href="http://neganov.blogspot.com/2010/10/decks-source-code-and-resources-from.html" target="_blank"&gt;unanswered items&lt;/a&gt; in my recent two presentations on Search at &lt;a title="Toronto SharePoint Users Group" href="http://www.meetup.com/TorontoSPUG/" target="_blank"&gt;TSPUG&lt;/a&gt; and &lt;a title="Mississauga SharePoint User Group" href="http://www.mspug.ca/" target="_blank"&gt;MSPUG&lt;/a&gt;, so I was driven to figure it out and eventually did get it to work although not without some controversial steps. In this post I chose to also describe other approaches I tried and things I learned along the way, which didn’t necessarily get me to the end goal but may still be useful in your specific scenario. If you are looking for just extending &lt;font face="Courier New"&gt;&lt;a title="Microsoft.Office.Server.Search.WebControls.CoreResultsWebPart" href="http://msdn.microsoft.com/en-us/library/microsoft.office.server.search.webcontrols.coreresultswebpart.aspx" target="_blank"&gt;CoreResultsWebPart&lt;/a&gt;&lt;/font&gt; so that it can “understand” FQL then you may want to scroll down a bit. You can download the complete source code &lt;a title="CoreResultsWebPartCustomization.zip" href="http://www.softforte.com/resources/coreresultswebpartcustomization.zip"&gt;here&lt;/a&gt;. I was testing my code on a SharePoint Server 2010 with December 2010 CU installed.&lt;/p&gt;  &lt;p&gt;As you may know search web parts in SharePoint 2010 are no longer sealed, which gives you lots of flexibility via extending them. &lt;font face="Courier New"&gt;CoreResultsWebPart&lt;/font&gt; is probably the most important of all and therefore it is a great candidate for being extended. I wanted to take a search phrase passed as a query string argument to a search results page and write my own FQL query using this phrase as a parameter. My FQL query would do something interesting with it, for example use XRANK to boost documents created by a particular author. I certainly wanted to leverage all the goodness of &lt;font face="Courier New"&gt;CoreResultsWebPart&lt;/font&gt;, just use my FQL query instead of a plain search phrase. Contrary to my expectations it turned out to be not trivial to accomplish. So let’s dive into the details.&lt;/p&gt;  &lt;p&gt;The story started with it completely not working, so I was forced to write a custom web part that used query object model and in particular the &lt;font face="Courier New"&gt;&lt;a title="Microsoft.Office.Server.Search.Query.KeywordQuery" href="http://msdn.microsoft.com/en-us/library/microsoft.office.server.search.query.keywordquery.aspx" target="_blank"&gt;KeywordQuery&lt;/a&gt;&lt;/font&gt; class to deal with queries written in FAST Query Language (FQL). This is the one I have demonstrated at MSPUG and (with little success) at TSPUG.&amp;#160; Below is a fragment showing how the query is submitted and results are rendered (BTW here is &lt;a title="Walkthrough: Creating a Basic Search Web Part Using the Query Object Model" href="http://msdn.microsoft.com/en-us/library/ms551453.aspx" target="_blank"&gt;related MSDN reference with example&lt;/a&gt;).&lt;/p&gt;  &lt;div&gt;   &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;span style="color: #0000ff"&gt;using&lt;/span&gt; (KeywordQuery q = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; KeywordQuery(ssaProxy))&lt;br /&gt; {&lt;br /&gt;     q.QueryText = fql;&lt;br /&gt;     q.EnableFQL = &lt;span style="color: #0000ff"&gt;true&lt;/span&gt;;&lt;br /&gt;     q.ResultTypes = ResultType.RelevantResults;&lt;br /&gt;     ResultTableCollection tables = q.Execute();&lt;br /&gt;     &lt;br /&gt;     &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (tables.Count == 0)&lt;br /&gt;     {&lt;br /&gt;         &lt;span style="color: #0000ff"&gt;return&lt;/span&gt;;&lt;br /&gt;     }&lt;br /&gt;&lt;br /&gt;     &lt;span style="color: #0000ff"&gt;using&lt;/span&gt; (ResultTable table = tables[ResultType.RelevantResults])&lt;br /&gt;     {&lt;br /&gt;         &lt;span style="color: #0000ff"&gt;while&lt;/span&gt; (table.Read())&lt;br /&gt;         {&lt;br /&gt;             &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; ordinal = table.GetOrdinal(&lt;span style="color: #006080"&gt;&amp;quot;Title&amp;quot;&lt;/span&gt;);&lt;br /&gt;             &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; title = table.GetString(ordinal);&lt;br /&gt;             TitleLabel.Controls.Add(&lt;br /&gt;                 &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; LiteralControl(&lt;br /&gt;                     String.Format(&lt;span style="color: #006080"&gt;&amp;quot;&amp;lt;br&amp;gt;{0}&amp;lt;/br&amp;gt;\r\n&amp;quot;&lt;/span&gt;, title)));&lt;br /&gt;         }&lt;br /&gt;&lt;br /&gt;         table.Close();&lt;br /&gt;     }&lt;br /&gt; }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;As you can see, rendering of results is very basic. Of course it can be made whatever it needs to be but why bother if there is CoreResultsWebPart around, which does it great already and is also highly customizable? So at this point I rolled up my sleeves. I have a book titled “&lt;a title="Professional SharePoint 2010 Development" href="http://www.wrox.com/WileyCDA/WroxTitle/Professional-SharePoint-2010-Development.productCd-0470529423.html" target="_blank"&gt;Professional SharePoint 2010 Development&lt;/a&gt;” with a red Boeing 767 on the cover, and in Chapter 6 there is a great discussion of how to extend &lt;font face="Courier New"&gt;CoreResultsWebPart&lt;/font&gt;. Also &lt;a title="Todd Carter" href="http://www.todd-carter.com/default.aspx" target="_blank"&gt;Todd Carter&lt;/a&gt; speaks about it and shows a demo &lt;a title="SharePoint 2010 Advanced Developer Training - Enterprise Search in SharePoint 2010" href="http://msdn.microsoft.com/en-us/sharepoint/ff420377.aspx" target="_blank"&gt;in his excellent video on Search&lt;/a&gt;. If you haven’t seen it I highly recommend spending an hour and 16 minutes watching it (Module 7). &lt;/div&gt;&lt;div&gt;Empowered with all this I wrote a web part that extended the &lt;font face="Courier New"&gt;CoreResultsWebPart&lt;/font&gt; and used a &lt;font face="Courier New"&gt;FixedQuery&lt;/font&gt; property to set a custom query, being almost one-to-one copy of Todd’s demo example. Here is the listing of this web part class (note how ConfigureDataSourceProperties() method override is used to set the &lt;font face="Courier New"&gt;FixedQuery&lt;/font&gt; property):&lt;/div&gt;&lt;div id="codeSnippetWrapper"&gt;&lt;br /&gt;  &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; ExtendedCoreResultsWebPartWithKeywordSyntax : CoreResultsWebPart&lt;br /&gt;{&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;protected&lt;/span&gt; &lt;span style="color: #0000ff"&gt;override&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; ConfigureDataSourceProperties()&lt;br /&gt;    {&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; LongQueryFormat = &lt;span style="color: #006080"&gt;&amp;quot;(FileExtension=\&amp;quot;doc\&amp;quot; OR FileExtension=\&amp;quot;docx\&amp;quot;) AND (Author:\&amp;quot;{0}\&amp;quot;)&amp;quot;&lt;/span&gt;;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; ShortQuery = &lt;span style="color: #006080"&gt;&amp;quot;(FileExtension=\&amp;quot;doc\&amp;quot; OR FileExtension=\&amp;quot;docx\&amp;quot;)&amp;quot;&lt;/span&gt;;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; query = &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (String.IsNullOrEmpty(AuthorToFilterBy))&lt;br /&gt;        {&lt;br /&gt;            query = ShortQuery;&lt;br /&gt;        }&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;else&lt;/span&gt;&lt;br /&gt;        {&lt;br /&gt;            query = String.Format(LongQueryFormat, AuthorToFilterBy);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.FixedQuery = query;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;base&lt;/span&gt;.ConfigureDataSourceProperties();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    [SPWebCategoryName(&lt;span style="color: #006080"&gt;&amp;quot;Custom&amp;quot;&lt;/span&gt;),&lt;br /&gt;    Personalizable(PersonalizationScope.Shared),&lt;br /&gt;    WebPartStorage(Storage.Shared),&lt;br /&gt;    WebBrowsable(&lt;span style="color: #0000ff"&gt;true&lt;/span&gt;),&lt;br /&gt;    WebDisplayName(&lt;span style="color: #006080"&gt;&amp;quot;Author to filter by&amp;quot;&lt;/span&gt;),&lt;br /&gt;    Description(&lt;span style="color: #006080"&gt;&amp;quot;First and last name of the author to filter results by.&amp;quot;&lt;/span&gt;)]&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; AuthorToFilterBy { get; set; }&lt;br /&gt;} &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The web part actually filters results by a given author. It uses &lt;em&gt;keyword query&lt;/em&gt; syntax and not the FQL so we are far from being done yet. Remember how in the previous code fragment there was a line &lt;font face="Courier New"&gt;&lt;strong&gt;q.EnableFQL = true;&lt;/strong&gt;&lt;/font&gt;? If just we could set it somewhere we would be essentially done! Well right but the &lt;font face="Courier New"&gt;KeywordQuery&lt;/font&gt; object is not directly accessible from the &lt;font face="Courier New"&gt;CoreResultsWebPart&lt;/font&gt; because it uses federation object model on top of the query object model (as do other search web parts). Purpose of the federation object model is sending same query to multiple search results providers and aggregating results later either in different spots on results page or in the same list. This is done by abstracting each search results provider by means of a &lt;font color="#333333" face="Courier New"&gt;&lt;a title="Microosft.Office.Server.Search.Query.Location" href="http://msdn.microsoft.com/en-us/library/microsoft.office.server.search.query.location.aspx" target="_blank"&gt;Location&lt;/a&gt;&lt;/font&gt; class. Important classes in federation object model are shown on the diagram below.&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&amp;#160;&lt;img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="image" border="0" alt="image" src="http://lh6.ggpht.com/_uLvQGkZ2Z10/TURujmuv3jI/AAAAAAAAADc/KgUZmz50fMs/image43.png?imgmax=800" width="690" height="687" /&gt; &lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;As you can see, &lt;font face="Courier New"&gt;CoreResultsWebPart&lt;/font&gt; is connected to the federation OM through &lt;font face="Courier New"&gt;CoreResultsDatasource&lt;/font&gt; and &lt;font face="Courier New"&gt;CoreResultsDatasourceView&lt;/font&gt; types with the latter actually doing all the hard work interacting with the model. And also our objective, the &lt;font face="Courier New"&gt;EnableFQL&lt;/font&gt; property, exists in the &lt;font face="Courier New"&gt;&lt;a title="Microsoft.Office.Server.Search.Query.FASTSearchRuntime" href="http://msdn.microsoft.com/en-us/library/microsoft.office.server.search.query.fastsearchruntime.aspx" target="_blank"&gt;FASTSearchRuntime&lt;/a&gt;&lt;/font&gt; class, which in turn sets this property on the &lt;font face="Courier New"&gt;KeywordQuery&lt;/font&gt; class, and as I showed at the beginning, this is what’s required to get FQL query syntax accepted.&lt;/div&gt;&lt;div&gt;As Todd Carter and the authors of Professional SharePoint 2010 Development point out, we need to extend the &lt;font face="Courier New"&gt;CoreResultsDatasourceView&lt;/font&gt; class in order to be able to control how our query is handled, and wire up our own class by also extending&lt;font face="Courier New"&gt; CoreResultsDatasource&lt;/font&gt; class. &lt;font face="Courier New"&gt;CoreResultsDatasourceView&lt;/font&gt; class creates a &lt;font color="#333333" face="Courier New"&gt;&lt;a title="Microsoft.Office.Server.Search.Query.LocationList" href="http://msdn.microsoft.com/en-us/library/microsoft.office.server.search.query.locationlist.aspx" target="_blank"&gt;LocationList&lt;/a&gt;&lt;/font&gt; with a single &lt;font face="Courier New"&gt;Location&lt;/font&gt; object and correctly determines which concrete implementation type of &lt;font color="#333333" face="Courier New"&gt;&lt;a title="Microsoft.Office.Server.Search.Query.ILocationRuntime" href="http://msdn.microsoft.com/en-us/library/microsoft.office.server.search.query.ilocationruntime.aspx" target="_blank"&gt;ILocationRuntime&lt;/a&gt;&lt;/font&gt; to wire up based on search service application configuration. In other words, federation by default is not happening for the &lt;font face="Courier New"&gt;CoreResultsWebPart&lt;/font&gt;. There is another web part, &lt;font color="#333333" face="Courier New"&gt;&lt;a title="How to: Enable HTML Rendering for the Federated Results Web Part" href="http://msdn.microsoft.com/en-us/library/cc789859.aspx" target="_blank"&gt;FederatedResultsWebPart&lt;/a&gt;&lt;/font&gt;, and another view class, &lt;font face="Courier New"&gt;FederatedResultsDatasourceView&lt;/font&gt;, whose purpose is to do exactly that. With that, let us get back to our objective.&lt;/div&gt;&lt;div&gt;If we were using SharePoint Enterprise Search then we would be almost done, because public virtual method &lt;font face="Courier New"&gt;AddSortOrder(SharePointSearchRuntime runtime)&lt;/font&gt; defined in the &lt;font face="Courier New"&gt;SearchResultsBaseDatasourceView&lt;/font&gt; class would let us get our hands on the instance of &lt;font face="Courier New"&gt;ILocationRuntime&lt;/font&gt;. But since we deal with &lt;font face="Courier New"&gt;FASTSearchRuntime&lt;/font&gt; we are sort of out of luck. Yes there exists a method overload &lt;font face="Courier New"&gt;AddSortOrder(FASTSearchRuntime runtime)&lt;/font&gt; but it is internal! This is where the controversy that I have mentioned at the beginning comes to play: I was not able to find a better way than to invoke an internal member via Reflection. My way works for me, but keep in mind that usually methods are made private or internal for a reason. I used Reflection to access internal property &lt;font face="Courier New"&gt;LocationRuntime&lt;/font&gt; of the &lt;font face="Courier New"&gt;Location&lt;/font&gt; object. I don’t know why this property is internal. If someone knows or has a better way to get at the &lt;font face="Courier New"&gt;FASTSearchRuntime&lt;/font&gt; instance or the &lt;font face="Courier New"&gt;KeywordQuery&lt;/font&gt; instance – please leave a comment! Here is a code fragment showing extension of the &lt;font face="Courier New"&gt;CoreResultsDatasourceView&lt;/font&gt; and getting an instance of &lt;font face="Courier New"&gt;FASTSearchRuntime&lt;/font&gt; from there.&lt;/div&gt;&lt;div id="codeSnippetWrapper"&gt;&lt;br /&gt;  &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;span style="color: #0000ff"&gt;class&lt;/span&gt; CoreFqlResultsDataSourceView : CoreResultsDatasourceView&lt;br /&gt;{&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; CoreFqlResultsDataSourceView(SearchResultsBaseDatasource dataSourceOwner, &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; viewName)&lt;br /&gt;        : &lt;span style="color: #0000ff"&gt;base&lt;/span&gt;(dataSourceOwner, viewName)&lt;br /&gt;    {&lt;br /&gt;        CoreFqlResultsDataSource fqlDataSourceOwner = &lt;span style="color: #0000ff"&gt;base&lt;/span&gt;.DataSourceOwner &lt;span style="color: #0000ff"&gt;as&lt;/span&gt; CoreFqlResultsDataSource;&lt;br /&gt;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (fqlDataSourceOwner == &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;)&lt;br /&gt;        {&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;throw&lt;/span&gt; &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; ArgumentOutOfRangeException();&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;override&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; SetPropertiesOnQdra()&lt;br /&gt;    {&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;base&lt;/span&gt;.SetPropertiesOnQdra();&lt;br /&gt;        &lt;span style="color: #008000"&gt;// At this point the query has not yet been dispatched to a search &lt;/span&gt;&lt;br /&gt;        &lt;span style="color: #008000"&gt;// location and we can set properties on that location, which will &lt;/span&gt;&lt;br /&gt;        &lt;span style="color: #008000"&gt;// let it understand the FQL syntax.&lt;/span&gt;&lt;br /&gt;        UpdateFastSearchLocation();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; UpdateFastSearchLocation()&lt;br /&gt;    {&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;base&lt;/span&gt;.LocationList == &lt;span style="color: #0000ff"&gt;null&lt;/span&gt; || 0 == &lt;span style="color: #0000ff"&gt;base&lt;/span&gt;.LocationList.Count)&lt;br /&gt;        {&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;return&lt;/span&gt;;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;foreach&lt;/span&gt; (Location location &lt;span style="color: #0000ff"&gt;in&lt;/span&gt; &lt;span style="color: #0000ff"&gt;base&lt;/span&gt;.LocationList)&lt;br /&gt;        {&lt;br /&gt;            &lt;span style="color: #008000"&gt;// We examine the contents of an internal &lt;/span&gt;&lt;br /&gt;            &lt;span style="color: #008000"&gt;// location.LocationRuntime property using Reflection. This is &lt;/span&gt;&lt;br /&gt;            &lt;span style="color: #008000"&gt;// the key step, which is also controversial since there is &lt;/span&gt;&lt;br /&gt;            &lt;span style="color: #008000"&gt;// probably a reason for not exposing the runtime publically.&lt;/span&gt;&lt;br /&gt;            Type locationType = location.GetType();&lt;br /&gt;            PropertyInfo info = locationType.GetProperty(&lt;br /&gt;                &lt;span style="color: #006080"&gt;&amp;quot;LocationRuntime&amp;quot;&lt;/span&gt;,&lt;br /&gt;                BindingFlags.NonPublic | BindingFlags.Instance,&lt;br /&gt;                &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;,&lt;br /&gt;                &lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(ILocationRuntime),&lt;br /&gt;                &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Type[0],&lt;br /&gt;                &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;);&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;object&lt;/span&gt; &lt;span style="color: #0000ff"&gt;value&lt;/span&gt; = info.GetValue(location, &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;);&lt;br /&gt;            FASTSearchRuntime runtime = &lt;span style="color: #0000ff"&gt;value&lt;/span&gt; &lt;span style="color: #0000ff"&gt;as&lt;/span&gt; FASTSearchRuntime;&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;null&lt;/span&gt; != runtime)&lt;br /&gt;            {&lt;br /&gt;                &lt;span style="color: #008000"&gt;// This is a FAST Search runtime. We can now enable FQL.&lt;/span&gt;&lt;br /&gt;                runtime.EnableFQL = &lt;span style="color: #0000ff"&gt;true&lt;/span&gt;;&lt;br /&gt;                &lt;span style="color: #0000ff"&gt;break&lt;/span&gt;;&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;By the way, another limitation of my approach is that using Reflection requires full trust CAS policy level. That said, finally we have arrived at our objective – we can set the flag on the &lt;font face="Courier New"&gt;FASTSearchRuntime&lt;/font&gt;, and it will understand our FQL queries. Our extended search results web part will show results as directed by the query (in the &lt;a title="CoreResultsWebPartCustomization.zip" href="http://www.softforte.com/resources/coreresultswebpartcustomization.zip"&gt;attached source code&lt;/a&gt; it uses XRANK) and leverage presentation richness of the &lt;font face="Courier New"&gt;CoreResultsWebPart&lt;/font&gt;.&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7384653670825187633-5813168160561710535?l=neganov.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://neganov.blogspot.com/2011/01/extending-coreresultswebpart-to-handle.html</link><author>noreply@blogger.com (Ivan Neganov)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh6.ggpht.com/_uLvQGkZ2Z10/TURujmuv3jI/AAAAAAAAADc/KgUZmz50fMs/s72-c/image43.png?imgmax=800" height="72" width="72" /><thr:total>3</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7384653670825187633.post-8790783665674466882</guid><pubDate>Fri, 21 Jan 2011 13:03:00 +0000</pubDate><atom:updated>2011-01-22T10:39:56.700-08:00</atom:updated><title>Decks and Source Code from January 19th TSPUG  Meeting</title><description>&lt;p&gt;Thanks to all who came to Wednesday’s &lt;a href="http://www.tspug.com"&gt;TSPUG&lt;/a&gt; meet up. I’ve uploaded a &lt;a title="Presentation Package TSPUG 2011-01-19" href="http://www.softforte.com/resources/tspug-2011-01-19.zip"&gt;package&lt;/a&gt; with presentation and source code files. I was able to resolve the first of the questions unanswered during &lt;a title="MSPUG presentation 2011-10-19" href="http://neganov.blogspot.com/2010/10/decks-source-code-and-resources-from.html"&gt;my previous talk about SharePoint search technologies&lt;/a&gt;. Although I meant to show it, I didn’t get to talk much about promoting user profile properties for selection in FAST user context for visual best bets. Basically as &lt;a title="Why do I get an access denied error when managing user contexts in SharePoint 2010" href="http://blogs.technet.com/b/speschka/archive/2010/02/22/why-do-i-get-an-access-denied-error-when-managing-user-contexts-in-sharepoint-2010.aspx" target="_blank"&gt;Steve Peschka has pointed out&lt;/a&gt;,&amp;#160; the first thing that needs to be done is permissions granted to the profile store. This will let you see the list of properties in his Property Explorer tool. Secondly, to promote profile properties to be available for selection in &lt;font face="Courier New"&gt;FAST Search user context &lt;/font&gt;administration section you need to edit value of &lt;font face="Courier New"&gt;FASTSearchContextProperties&lt;/font&gt; property of FAST Query search service application (SSA). I wrote a command-line utility for this purpose, which can be invoked as follows:&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;FASTProfilePropertyUpdater.exe –ssaId &amp;lt;FAST query SSA Guid&amp;gt; -action Add|Remove -property &amp;lt;User Profile property name&amp;gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;Code fragment below demonstrates how SSA reference is acquired and the “Add” operation is accomplished. Full source code is a part of the package. Ideally you want to use PowerShell script to manage this, I just wrote an executable as it was easier to get it working quickly for me. &lt;/p&gt;  &lt;div id="codeSnippetWrapper"&gt;   &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;SPFarm farm = SPFarm.Local;&lt;br /&gt; var settingsService = SPFarm.Local.Services.GetValue&amp;lt;SearchQueryAndSiteSettingsService&amp;gt;();&lt;br /&gt; var serviceApp = settingsService.Applications[ssaId];&lt;br /&gt; var searchApp = serviceApp &lt;span style="color: #0000ff"&gt;as&lt;/span&gt; SearchServiceApplication;&lt;br /&gt;&lt;br /&gt; &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;null&lt;/span&gt; == searchApp)&lt;br /&gt; {&lt;br /&gt;     Console.WriteLine(&lt;br /&gt;         &lt;span style="color: #006080"&gt;&amp;quot;Cannot find search service application with the ID '{0}'.&amp;quot;&lt;/span&gt;, &lt;br /&gt;         ssaId);&lt;br /&gt;     &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; 2;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; properties = (String)searchApp.Properties[FASTSearchContextProperties];&lt;br /&gt; Console.WriteLine(&lt;br /&gt;     &lt;span style="color: #006080"&gt;&amp;quot;Updating service application properties for property key '{0}'... Value before update was: '{1}'&amp;quot;&lt;/span&gt;,&lt;br /&gt;     FASTSearchContextProperties,&lt;br /&gt;     properties);&lt;br /&gt; List&amp;lt;&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;&amp;gt; propertiesList = properties.Split(&lt;span style="color: #006080"&gt;','&lt;/span&gt;).&lt;br /&gt;     Select(p =&amp;gt; p.Trim()).ToList();&lt;br /&gt; &lt;br /&gt; &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (ContextPropertyActions.Add == action &amp;amp;&amp;amp;&lt;br /&gt;     properties.IndexOf(propertyName, StringComparison.Ordinal) &amp;lt; 0)&lt;br /&gt; {&lt;br /&gt;     propertiesList.Add(propertyName);&lt;br /&gt;     properties = &lt;span style="color: #0000ff"&gt;string&lt;/span&gt;.Join(&lt;span style="color: #006080"&gt;&amp;quot;,&amp;quot;&lt;/span&gt;, propertiesList.ToArray());&lt;br /&gt;     searchApp.Properties[FASTSearchContextProperties] = properties;&lt;br /&gt;     searchApp.Update(&lt;span style="color: #0000ff"&gt;true&lt;/span&gt;);&lt;br /&gt;     Console.WriteLine(&lt;span style="color: #006080"&gt;&amp;quot;Property added. Updated value is: '{0}'.&amp;quot;&lt;/span&gt;, properties);&lt;br /&gt;     &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; 0;&lt;br /&gt; }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Also in the package is the source code for a web part demonstrating how to dynamically boost search relevance ranking from within an FQL query by using XRANK keyword.The demo of this web part didn’t go well, but the code is actually working (I dragged the wrong web part to the page during presentation!). Also someone has asked me about proximity-based filtering of results in FAST query language. Yes this is possible&amp;#160; - &lt;a title="FAST Query Language Operations" href="http://msdn.microsoft.com/en-us/library/ff394462.aspx" target="_blank"&gt;there is a number of keywords that support this&lt;/a&gt;. &lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7384653670825187633-8790783665674466882?l=neganov.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://neganov.blogspot.com/2011/01/decks-from-january-19th-tspug-meeting.html</link><author>noreply@blogger.com (Ivan Neganov)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7384653670825187633.post-5830715909350352710</guid><pubDate>Sun, 09 Jan 2011 03:18:00 +0000</pubDate><atom:updated>2011-01-10T08:15:48.901-08:00</atom:updated><title>Automate Internet Proxy Management with PowerShell</title><description>&lt;p&gt;The solution is very simple, yet the issue was so annoying to me that I thought to share this. I have a laptop and do work on it on site at my client and when I am at home. When I am in the office connected to my client’s network I need to use a proxy to access the Internet, while usually I do not need a proxy when I am located elsewhere. You normally set up a proxy using browser settings. With Internet Explorer 8 you open a browser, then go to &lt;strong&gt;Tools &amp;gt;&amp;gt; Internet Options &amp;gt;&amp;gt; Connections &amp;gt;&amp;gt; LAN Settings&lt;/strong&gt;. There you configure the proxy parameters. As a part of configuration you can turn the proxy on or off by setting or clearing a &lt;strong&gt;Use a proxy server for your LAN &lt;/strong&gt;check box, and as you switch the proxy the rest of your proxy configuration settings such as exceptions is preserved for you. Great!&lt;/p&gt;  &lt;p&gt;My problem was that on almost daily basis I had to open the browser, navigate to settings then check or uncheck that box. I would come to work and forget to go through the steps so my browser would get stuck, and then I would go “oh yeah, I turned the proxy off last night”. Of course the reverse would happen at home… I tolerated this too long because I didn’t expect that a simple solution exists, but it does and here it is:&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;font face="Courier New"&gt;HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings\ProxyEnable &lt;/font&gt;key stores a DWORD value, either 1 or 0 to indicate if the proxy is enabled. &lt;/p&gt;  &lt;p&gt;So I wrote two 1-line PowerShell scripts and added two shortcuts to them to my Windows taskbar: Enable Proxy, Disable Proxy! Here is how the script to enable proxy looks like:&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;Set-ItemProperty &amp;quot;HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings&amp;quot; -Name ProxyEnable -Value 1&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;Then I’ve got excited, and wrote yet another rock star PowerShell script. Here it is:&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;$matches = @(ipconfig /all | findstr &amp;quot;myclientdomain&amp;quot;)     &lt;br /&gt;if($matches.Count -gt 0){      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; ./EnableProxy.ps1      &lt;br /&gt;}else{      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; ./DisableProxy.ps1      &lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;That’s right I am using output of the ipconfig command to determine if I am on the client’s network and if yes then I turn on my proxy. After I have added a scheduled task running at user logon to invoke this script, the quality of my professional life has improved.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7384653670825187633-5830715909350352710?l=neganov.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://neganov.blogspot.com/2011/01/automate-internet-proxy-management-with.html</link><author>noreply@blogger.com (Ivan Neganov)</author><thr:total>2</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7384653670825187633.post-7434132947817462162</guid><pubDate>Thu, 23 Dec 2010 22:45:00 +0000</pubDate><atom:updated>2011-02-24T13:35:42.855-08:00</atom:updated><title>Writing Trace Output to ULS Log in SharePoint 2010</title><description>&lt;p&gt;SharePoint 2010 supports writing custom messages to ULS log. A &lt;a title="Logging to ULS in SharePoint 2010" href="http://blog.mastykarz.nl/logging-uls-sharepoint-2010/" target="_blank"&gt;blog post&lt;/a&gt; by Waldek Mastykarz of &lt;a title="Mavention" href="http://www.mavention.nl/" target="_blank"&gt;Mavention&lt;/a&gt; provides a good example of how to do this. &lt;strong&gt;UPDATE 02/24/2011:&lt;/strong&gt; &lt;A href="http://msdn.microsoft.com/en-us/library/gg512103.aspx#bk_splog" target="_blank"&gt;Andrew Connell's article on MSDN from December 2010&lt;/a&gt; provides essential information on diagnostics logging.&lt;/p&gt;&lt;p&gt;Ability to send messages from &lt;a title="System.Diagnostics.Trace" href="http://msdn.microsoft.com/en-us/library/system.diagnostics.trace.aspx" target="_blank"&gt;System.Diagnostics.Trace&lt;/a&gt;.Write() and Trace.Fail() method overloads to ULS is yet another “logging novelty” I will be focusing on in this post.&lt;/p&gt;  &lt;p&gt;There is a new type in Microsoft.SharePoint assembly, which was not there in version 12 – &lt;a title="Microsoft.SharePoint.SPULSTraceListener" href="http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.spulstracelistener.aspx" target="_blank"&gt;Microsoft.SharePoint.SPULSTraceListener&lt;/a&gt;. As its name suggests it allows sending trace messages to ULS. &lt;/p&gt;  &lt;p&gt;If you are instrumenting your custom SharePoint code and need to write diagnostic traces to ULS then you can wire up SPULSTraceListener type in your web.config and use tracing infrastructure available in &lt;font face="Courier New"&gt;System.Diagnostics.Trace&lt;/font&gt;.&amp;#160; Here are the steps:&lt;/p&gt;  &lt;p&gt;1. Add a trace listener element to web.config. For more information see description of &lt;a title="system.diagnostics configuration element on MSDN" href="http://msdn.microsoft.com/en-us/library/1txedc80.aspx" target="_blank"&gt;system.diagnostics&lt;/a&gt; element on MSDN.&lt;/p&gt;  &lt;div id="codeSnippetWrapper"&gt;   &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;system.diagnostics&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;trace&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;listeners&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;remove&lt;/span&gt; &lt;span style="color: #ff0000"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;Default&amp;quot;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;add&lt;/span&gt; &lt;br /&gt;                &lt;span style="color: #ff0000"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;ULSTraceListener&amp;quot;&lt;/span&gt; &lt;br /&gt;                &lt;span style="color: #ff0000"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;Microsoft.SharePoint.SPULSTraceListener, Microsoft.SharePoint, version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c&amp;quot;&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;listeners&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;trace&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;system.diagnostics&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;In this XML snippet note the &lt;strong&gt;&amp;lt;remove name=”Default”&amp;gt;&lt;/strong&gt;. This is done to remove &lt;a title="DefaultTraceListener" href="http://msdn.microsoft.com/en-us/library/system.diagnostics.defaulttracelistener.aspx" target="_blank"&gt;default trace listener&lt;/a&gt;, which is wired up by default and displays a pop-up window with the message when &lt;font face="Courier New"&gt;Trace.Fail()&lt;/font&gt; is called.&lt;/div&gt;&lt;p&gt;2. In central administration site configure diagnostic logging (Central Administration &amp;gt;&amp;gt; Diagnostic Logging). If you are using &lt;font face="Courier New"&gt;Trace.Write()&lt;/font&gt; method calls then they are logged as &lt;strong&gt;Verbose &lt;/strong&gt;and so in order to actually see them in ULS logs you need to make sure that throttling level is set to &lt;strong&gt;Verbose&lt;/strong&gt; for &lt;strong&gt;SharePoint Foundation &amp;gt; Service Connections &lt;/strong&gt;category. If you use &lt;font face="Courier New"&gt;Trace.Fail()&lt;/font&gt; overloaded methods then the message will be written as a &lt;strong&gt;High &lt;/strong&gt;level, which by default is on, so the message will normally end up being written to a log file. And yes, all messages will be written to the log under &lt;strong&gt;Service Connections&lt;/strong&gt; category.&lt;/p&gt;&lt;br /&gt;&lt;h5&gt;What About TraceContext.Write()?&lt;/h5&gt;&lt;p&gt;&lt;font face="Courier New"&gt;UserControl&lt;/font&gt;, &lt;font face="Courier New"&gt;Page&lt;/font&gt; and &lt;font face="Courier New"&gt;HttpContext&lt;/font&gt; classes have a property named &lt;strong&gt;Trace&lt;/strong&gt; of type &lt;a title="System.Web.TraceContext" href="http://msdn.microsoft.com/en-us/library/system.web.tracecontext.aspx" target="_blank"&gt;System.Web.TraceContext&lt;/a&gt;. It allows tracing messages using ASP.NET trace infrastructure, for example: &lt;font face="Courier New"&gt;HttpContext.Current.Trace.Write(string message);.&lt;/font&gt; You can send ASP.NET trace messages to ULS using standard technique but with a caveat: &lt;/p&gt;&lt;p&gt;Add &lt;a title="trace Element" href="http://msdn.microsoft.com/en-us/library/6915t83k.aspx"&gt;trace&lt;/a&gt; configuration element under system.web element in your web.config as follows:&lt;/p&gt;&lt;div&gt;&lt;br /&gt;  &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;system.web&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;trace&lt;/span&gt; &lt;span style="color: #ff0000"&gt;enabled&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;true&amp;quot;&lt;/span&gt; &lt;span style="color: #ff0000"&gt;requestLimit&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;1000&amp;quot;&lt;/span&gt; &lt;span style="color: #ff0000"&gt;mostRecent&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;true&amp;quot;&lt;/span&gt; &lt;span style="color: #ff0000"&gt;writeToDiagnosticsTrace&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;true&amp;quot;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;    ...&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Here the key attribute is &lt;font face="Courier New"&gt;writeToDiagnosticsTrace&lt;/font&gt; instructing ASP.NET trace to use tracing infrastructure from System.Diagnostics. Now trace messages written using &lt;font face="Courier New"&gt;TraceContext.Write()&lt;/font&gt; will be sent to ULS.&lt;/div&gt;&lt;div&gt;Now the caveat: adding &lt;font face="Courier New"&gt;system.web/trace&lt;/font&gt; element appears to destabilize SharePoint. I have tried this on SharePoint Foundation and SharePoint Server 2010 with October 2010 CU, and although tracing does work as expected I have got a consistent error when trying to create a new web part page:&lt;/div&gt;&lt;div&gt;&lt;a href="http://lh4.ggpht.com/_uLvQGkZ2Z10/TRPRGBbwh4I/AAAAAAAAADU/OequMgi6-lA/s1600-h/UIErrorFromTracing%5B4%5D.jpg"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="UIErrorFromTracing" border="0" alt="UIErrorFromTracing" src="http://lh6.ggpht.com/_uLvQGkZ2Z10/TRPRGbBB54I/AAAAAAAAADY/7PwijdGvTrU/UIErrorFromTracing_thumb%5B2%5D.jpg?imgmax=800" width="580" height="258" /&gt;&lt;/a&gt; &lt;/div&gt;&lt;div&gt;Looking at the ULS log, I found these messages logged under SharePoint Foundation category:&lt;/div&gt;&lt;p&gt;&lt;font size="1" face="Courier New"&gt;SharePoint Foundation&amp;#160;&amp;#160;&amp;#160; General&amp;#160;&amp;#160;&amp;#160; b9y3&amp;#160;&amp;#160;&amp;#160; High&amp;#160;&amp;#160;&amp;#160; Failed to open the file 'C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\Resources\wss.resx'.&lt;br /&gt;    &lt;br /&gt;SharePoint Foundation&amp;#160;&amp;#160;&amp;#160; General&amp;#160;&amp;#160;&amp;#160; b9y4&amp;#160;&amp;#160;&amp;#160; High&amp;#160;&amp;#160;&amp;#160; #20015: Cannot open &amp;quot;&amp;quot;: no such file or folder.&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;SharePoint Foundation&amp;#160;&amp;#160;&amp;#160; General&amp;#160;&amp;#160;&amp;#160; b9y4&amp;#160;&amp;#160;&amp;#160; High&amp;#160;&amp;#160;&amp;#160; (#2: Cannot open &amp;quot;&amp;quot;: no such file or folder.)&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;SharePoint Foundation&amp;#160;&amp;#160;&amp;#160; General&amp;#160;&amp;#160;&amp;#160; b9y9&amp;#160;&amp;#160;&amp;#160; High&amp;#160;&amp;#160;&amp;#160; Failed to read resource file &amp;quot;C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\Resources\wss.resx&amp;quot; from feature id &amp;quot;(null)&amp;quot;.&lt;/font&gt;&lt;/p&gt;&lt;div&gt;&amp;#160;&lt;/div&gt;&lt;div&gt;As soon as I disable the &lt;font face="Courier New"&gt;system.web/tracing&lt;/font&gt; the error disappears. I am not sure if this is a bug or adding &amp;lt;trace&amp;gt; element under &amp;lt;system.web&amp;gt; is not supported. In any case there is enough of rich diagnostic features available, and if you are using tracing in your application then just avoid &lt;font face="Courier New"&gt;System.Web.TraceContext.Write()&lt;/font&gt; in favor of &lt;font face="Courier New"&gt;System.Diagnostics.Trace.Write() &lt;/font&gt;or at least use it temporarily if you need to. By the way &lt;font face="Courier New"&gt;System.Diagnostics.Debug.Write()&lt;/font&gt; also sends messages to trace log.&lt;/div&gt;&lt;p&gt;&lt;strong style="color:red"&gt;UPDATE (01-16-2011):&lt;/strong&gt; There is yet another issue caused by turning on trace that I ran into today: SharePoint designer cannot open a site in a web application for which tracing is enabled, and keeps prompting for credentials. If you check out traffic with Fiddler, you will find that SPD makes requests to http://devserver2010/_vti_bin/shtml.dll/_vti_rpc, which return a 401 UNAUTHORIZED. Not even verbose logging reveals anything useful. Well, commenting out &amp;lt;trace&amp;gt; element in web.config restores normal functionality.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7384653670825187633-7434132947817462162?l=neganov.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://neganov.blogspot.com/2010/12/writing-trace-output-to-uls-log-in.html</link><author>noreply@blogger.com (Ivan Neganov)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh6.ggpht.com/_uLvQGkZ2Z10/TRPRGbBB54I/AAAAAAAAADY/7PwijdGvTrU/s72-c/UIErrorFromTracing_thumb%5B2%5D.jpg?imgmax=800" height="72" width="72" /><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7384653670825187633.post-7015463810052257156</guid><pubDate>Mon, 13 Dec 2010 18:04:00 +0000</pubDate><atom:updated>2010-12-13T12:09:39.113-08:00</atom:updated><title>Configure Links Web Part to Open URLs In a New Window With SharePoint 2010</title><description>&lt;p&gt;With SharePoint 2010 (or SharePoint Foundation 2010) you can customize list views using XSLT, which is very powerful and for simple changes also quite simple. Here is an example of how to make URLs in Links list web part open up pages in a new browser window.&lt;/p&gt;  &lt;p&gt;Links web part as well as other list-based web parts uses a predefined list view to render its content. Since views are now defined using XSLT style sheets, all that is needed to control the HTML is to override appropriate XSLT template with a custom one that has HTML markup that we need, for example &amp;lt;a href=”….” &lt;strong&gt;target=”_blank”&lt;/strong&gt;&amp;gt;. List web part’s edit mode panel contains a text field titled &lt;strong&gt;XSL Link&lt;/strong&gt; under Miscellaneous category where you can provide a URL of an XSLT file, which will override default rendering behavior. &lt;/p&gt;  &lt;p&gt;Let’s say we have a Links list with a few URLs in it and we have added a Links web part to a page. We want to have all links shown by the web part open up in a new window. We need to find an XSLT template which describes rendering of the field with a link. One easy way to determine this is to sort by the URL field then take a note of the value of &lt;strong&gt;SortField&lt;/strong&gt; query string value, which tells us that the field name we need is &lt;strong&gt;URLNoMenu&lt;/strong&gt;. URL field is not a part of default view, default view has a &lt;b&gt;URL (URL with edit menu)&lt;/b&gt; column, so you would need to add a column titled &lt;b&gt;URL&lt;/b&gt;. As shown in the picture below, I’ve added my own view “Only Url” to Links list with this field only and set the web part to use this view.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_uLvQGkZ2Z10/TQZgLMJEdcI/AAAAAAAAADI/RkS_Lf_0P-4/s1600-h/LinksListExample%5B6%5D.jpg"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="LinksListExample" border="0" alt="LinksListExample" src="http://lh6.ggpht.com/_uLvQGkZ2Z10/TQZgLqjRhqI/AAAAAAAAADM/9iSlyqh3ywM/LinksListExample_thumb%5B4%5D.jpg?imgmax=800" width="896" height="683" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Now we need to find an XSLT template for the URLNoMenu field.&amp;#160; Out-Of-The-Box templates are stored under the &lt;strong&gt;14&lt;/strong&gt; hive in TEMPLATE\LAYOUTS\XSL on server file system. For what we need there are 2 important files there: &lt;strong&gt;main.xsl&lt;/strong&gt; and &lt;strong&gt;fldtypes.xsl&lt;/strong&gt;. The former file is a default file used for formatting, which imports other XSLT files including fldtypes.xsl. The latter file is the one which contains many templates for rendering different fields. Doing search inside this file for URLNoMenu yields: &lt;/p&gt;  &lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #c71585"&gt;xsl&lt;/span&gt;:&lt;span style="color: #800000"&gt;template&lt;/span&gt; &lt;span style="color: #ff0000"&gt;name&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;&amp;quot;FieldRef_URLNoMenu_body&amp;quot;&lt;/span&gt; &lt;span style="color: #ff0000"&gt;ddwrt&lt;/span&gt;:&lt;span style="color: #ff0000"&gt;dvt_mode&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;&amp;quot;body&amp;quot;&lt;/span&gt; &lt;span style="color: #ff0000"&gt;match&lt;/span&gt; =&lt;span style="color: #0000ff"&gt;&amp;quot;FieldRef[@Name='URLNoMenu']&amp;quot;&lt;/span&gt; &lt;span style="color: #ff0000"&gt;mode&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;&amp;quot;Computed_body&amp;quot;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Next we copy this template XML element and put it in a new XSLT file. I named mine &lt;strong&gt;TargetBlank.xsl. &lt;/strong&gt;Inside the new file we change HTML anchor tag to include target=”_blank” (or anything else we need) and save the file. Once we specify URL to this new file in the &lt;strong&gt;XSL Link&lt;/strong&gt; field of a web part being edited, it will override all default formatting, therefore we also need to make sure that other templates still apply. Thanks to XSL import and overriding mechanism this is easy to do, we just need to import &lt;strong&gt;main.xsl&lt;/strong&gt; file, and our version of the &lt;strong&gt;FieldRef_URLNoMenu_body&lt;/strong&gt; template will override the one located inside fldtypes.xsl. Here is the complete listing of the &lt;strong&gt;TargetBlank.xsl.&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;xsl:stylesheet&lt;/span&gt; &lt;span style="color: #ff0000"&gt;xmlns:x&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;http://www.w3.org/2001/XMLSchema&amp;quot;&lt;/span&gt; &lt;br /&gt;                &lt;span style="color: #ff0000"&gt;xmlns:d&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;http://schemas.microsoft.com/sharepoint/dsp&amp;quot;&lt;/span&gt; &lt;br /&gt;                &lt;span style="color: #ff0000"&gt;version&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;1.0&amp;quot;&lt;/span&gt; &lt;br /&gt;                &lt;span style="color: #ff0000"&gt;exclude-result-prefixes&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;xsl msxsl ddwrt&amp;quot;&lt;/span&gt; &lt;br /&gt;                &lt;span style="color: #ff0000"&gt;xmlns:ddwrt&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;http://schemas.microsoft.com/WebParts/v2/DataView/runtime&amp;quot;&lt;/span&gt; &lt;br /&gt;                &lt;span style="color: #ff0000"&gt;xmlns:asp&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;http://schemas.microsoft.com/ASPNET/20&amp;quot;&lt;/span&gt; &lt;br /&gt;                &lt;span style="color: #ff0000"&gt;xmlns:__designer&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;http://schemas.microsoft.com/WebParts/v2/DataView/designer&amp;quot;&lt;/span&gt; &lt;br /&gt;                &lt;span style="color: #ff0000"&gt;xmlns:xsl&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;http://www.w3.org/1999/XSL/Transform&amp;quot;&lt;/span&gt; &lt;br /&gt;                &lt;span style="color: #ff0000"&gt;xmlns:msxsl&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;urn:schemas-microsoft-com:xslt&amp;quot;&lt;/span&gt; &lt;br /&gt;                &lt;span style="color: #ff0000"&gt;xmlns:SharePoint&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;Microsoft.SharePoint.WebControls&amp;quot;&lt;/span&gt; &lt;br /&gt;                &lt;span style="color: #ff0000"&gt;xmlns:ddwrt2&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;urn:frontpage:internal&amp;quot;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;xsl:import&lt;/span&gt; &lt;span style="color: #ff0000"&gt;href&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;/_layouts/xsl/main.xsl&amp;quot;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt; &lt;br /&gt;    &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;xsl:output&lt;/span&gt; &lt;span style="color: #ff0000"&gt;method&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;html&amp;quot;&lt;/span&gt; &lt;span style="color: #ff0000"&gt;indent&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;no&amp;quot;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;xsl:template&lt;/span&gt; &lt;span style="color: #ff0000"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;FieldRef_URLNoMenu_body&amp;quot;&lt;/span&gt; &lt;br /&gt;                  &lt;span style="color: #ff0000"&gt;ddwrt:dvt_mode&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;body&amp;quot;&lt;/span&gt; &lt;br /&gt;                  &lt;span style="color: #ff0000"&gt;match&lt;/span&gt; &lt;span style="color: #0000ff"&gt;=&amp;quot;FieldRef[@Name='URLNoMenu']&amp;quot;&lt;/span&gt; &lt;br /&gt;                  &lt;span style="color: #ff0000"&gt;mode&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;Computed_body&amp;quot;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;xsl:param&lt;/span&gt; &lt;span style="color: #ff0000"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;thisNode&amp;quot;&lt;/span&gt; &lt;span style="color: #ff0000"&gt;select&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;.&amp;quot;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;xsl:variable&lt;/span&gt; &lt;span style="color: #ff0000"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;url&amp;quot;&lt;/span&gt; &lt;span style="color: #ff0000"&gt;select&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;$thisNode/@URL&amp;quot;&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;xsl:variable&lt;/span&gt; &lt;span style="color: #ff0000"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;desc&amp;quot;&lt;/span&gt; &lt;span style="color: #ff0000"&gt;select&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;$thisNode/@URL.desc&amp;quot;&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;xsl:choose&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;xsl:when&lt;/span&gt; &lt;span style="color: #ff0000"&gt;test&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;$url=''&amp;quot;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;                &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;xsl:value-of&lt;/span&gt; &lt;span style="color: #ff0000"&gt;select&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;$desc&amp;quot;&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;xsl:when&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;xsl:otherwise&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;                &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;xsl:choose&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;                    &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;xsl:when&lt;/span&gt; &lt;span style="color: #ff0000"&gt;test&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;@Format='Image'&amp;quot;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;                        &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;img&lt;/span&gt; &lt;span style="color: #ff0000"&gt;onfocus&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;OnLink(this)&amp;quot;&lt;/span&gt; &lt;span style="color: #ff0000"&gt;src&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;{$url}&amp;quot;&lt;/span&gt; &lt;span style="color: #ff0000"&gt;alt&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;{$desc}&amp;quot;&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;                    &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;xsl:when&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;                    &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;xsl:otherwise&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;                        &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;a&lt;/span&gt; &lt;span style="color: #ff0000"&gt;onfocus&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;OnLink(this)&amp;quot;&lt;/span&gt; &lt;span style="color: #ff0000"&gt;href&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;{$url}&amp;quot;&lt;/span&gt; &lt;span style="color: #ff0000"&gt;target&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;_blank&amp;quot;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;                            &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;xsl:choose&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;                                &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;xsl:when&lt;/span&gt; &lt;span style="color: #ff0000"&gt;test&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;$desc=''&amp;quot;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;                                    &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;xsl:value-of&lt;/span&gt; &lt;span style="color: #ff0000"&gt;select&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;$url&amp;quot;&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;                                &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;xsl:when&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;                                &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;xsl:otherwise&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;                                    &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;xsl:value-of&lt;/span&gt; &lt;span style="color: #ff0000"&gt;select&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;$desc&amp;quot;&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;                                &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;xsl:otherwise&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;                            &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;xsl:choose&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;                        &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;a&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;                    &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;xsl:otherwise&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;                &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;xsl:choose&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;xsl:otherwise&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;xsl:choose&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;xsl:template&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;xsl:stylesheet&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;In this file the &lt;strong&gt;xsl:stylesheet &lt;/strong&gt;element is copied from the &lt;strong&gt;main.xsl&lt;/strong&gt; file. Also note the &lt;strong&gt;xsl:import &lt;/strong&gt;and the &lt;strong&gt;xsl:output &lt;/strong&gt;statements. Lastly we need to upload the XSLT file and reference its URL in the &lt;strong&gt;XSL Link&lt;/strong&gt; field of our web part. That’s all there is to it. Our links should now open in a new browser window.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7384653670825187633-7015463810052257156?l=neganov.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://neganov.blogspot.com/2010/12/open-links-in-new-window-and-more-with.html</link><author>noreply@blogger.com (Ivan Neganov)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh6.ggpht.com/_uLvQGkZ2Z10/TQZgLqjRhqI/AAAAAAAAADM/9iSlyqh3ywM/s72-c/LinksListExample_thumb%5B4%5D.jpg?imgmax=800" height="72" width="72" /><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7384653670825187633.post-4959550088501888846</guid><pubDate>Wed, 20 Oct 2010 18:01:00 +0000</pubDate><atom:updated>2011-01-29T12:13:52.809-08:00</atom:updated><title>Decks, Source Code and Resources from October 19 MSPUG Meeting</title><description>&lt;p&gt;Thanks a lot to the folks who showed up yesterday at the Mississauga User Group meeting. Also I’d like to thank Ray Outair for his efforts in running the group in celebration of its first year anniversary. I have posted the deck for my presentation “Leveraging SharePoint 2010 Search Technologies” and the source code of the demo web part demonstrating FQL capabilities on &lt;a title="SoftForte Resources" href="http://www.softforte.com/Resources.htm" target="_blank"&gt;SoftForte site here&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;If you are planning search deployment I highly recommend checking out technical diagrams on TechNet: &lt;a title="http://technet.microsoft.com/en-ca/library/cc263199.aspx" href="http://technet.microsoft.com/en-ca/library/cc263199.aspx"&gt;http://technet.microsoft.com/en-ca/library/cc263199.aspx&lt;/a&gt;. There are 4 diagrams there dedicated specifically to Search. Also check out downloadable content here &lt;a title="http://technet.microsoft.com/en-ca/library/cc262788.aspx" href="http://technet.microsoft.com/en-ca/library/cc262788.aspx"&gt;http://technet.microsoft.com/en-ca/library/cc262788.aspx&lt;/a&gt; – it has been recently updated.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;img style="BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; MARGIN: 0px 30px 0px 0px; DISPLAY: inline; BORDER-TOP: 0px; BORDER-RIGHT: 0px" title="Search" border="0" alt="Search" align="left" src="http://lh4.ggpht.com/_uLvQGkZ2Z10/TL8uX2KVhSI/AAAAAAAAADE/Tt17bhCA838/Search%5B10%5D.jpg?imgmax=800" width="100" height="125" /&gt; &lt;/p&gt;&lt;p&gt;As I mentioned at the meeting, I also recommend a book titled &lt;a title="Professional Microsoft Search: FAST Search, SharePoint Search, and Search Server" href="http://www.wrox.com/WileyCDA/WroxTitle/Professional-Microsoft-Search-FAST-Search-SharePoint-Search-and-Search-Server.productCd-0470584661.html" target="_blank"&gt;Professional Microsoft Search: FAST Search, SharePoint Search, and Search Server&lt;/a&gt; by Mark Bennett, Jeff Fried, Miles Kehoe and Natalya Voskresenskaya. It is a great resource on planning and architecture of SharePoint Enterprise Search, and specifically FAST Search products.&lt;/p&gt;&lt;p&gt;Last but not least is a reference to &lt;a title="Steve Peschka's Search Explorer" href="http://blogs.technet.com/b/speschka/archive/2010/08/15/free-developer-search-tool-for-sharepoint-2010-search-and-fast-search-for-sharepoint.aspx" target="_blank"&gt;Steve Peschka’s blog post&lt;/a&gt; where Steve introduces a Search Explorer tool that he wrote. Steve’s blog is an essential resource on developing Search and other SharePoint development topics.&lt;/p&gt;&lt;p&gt; &lt;/p&gt;&lt;p&gt;So I’d like to re-cap on a few questions we left unanswered yesterday:&lt;/p&gt;&lt;p&gt;1. FAST visual best bets were displayed, but did not get filtered based on User Context’s managed properties. The question is how to create/promote properties into user context for such filtering to happen correctly. &lt;strong&gt;UPDATE:&lt;/strong&gt; &lt;a href="http://neganov.blogspot.com/2011/01/decks-from-january-19th-tspug-meeting.html"&gt;I figured this one out&lt;/a&gt;&lt;/p&gt;&lt;p&gt;2. I was not lucky extending &lt;a title="Microsoft.Office.Server.Search.WebControls.CoreResultsWebPart" href="http://msdn.microsoft.com/en-us/library/microsoft.office.server.search.webcontrols.coreresultswebpart.aspx" target="_blank"&gt;CoreResultsWebPart&lt;/a&gt; and make it process custom FQL queries, and was forced instead to write a web part from scratch. The question is whether there is a supported way to extend CoreResultsWebPart for FAST search queries.&lt;br&gt;&lt;strong&gt;UPDATE:&lt;/strong&gt; this one is now also addressed. Check it out &lt;a href="http://neganov.blogspot.com/2011/01/extending-coreresultswebpart-to-handle.html"&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;3. Somebody has mentioned that they could not get PowerPoint visual preview to work with FAST search results, suspecting that SSL encryption between FAST Search Server and query SSA was to blame. Looks like some research is needed here.&lt;/p&gt;&lt;p&gt;I plan to look into these and post my findings. Please feel free to comment on if you get answers sooner.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7384653670825187633-4959550088501888846?l=neganov.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://neganov.blogspot.com/2010/10/decks-source-code-and-resources-from.html</link><author>noreply@blogger.com (Ivan Neganov)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh4.ggpht.com/_uLvQGkZ2Z10/TL8uX2KVhSI/AAAAAAAAADE/Tt17bhCA838/s72-c/Search%5B10%5D.jpg?imgmax=800" height="72" width="72" /><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7384653670825187633.post-4254719022483682291</guid><pubDate>Sun, 19 Sep 2010 17:43:00 +0000</pubDate><atom:updated>2010-12-07T14:46:48.814-08:00</atom:updated><title>Enumerate SharePoint 2010 Databases</title><description>&lt;p&gt;If you are working with SharePoint in a lab environment and use one shared database server to store databases from multiple farms then with SharePoint 2010 you can quickly lose control of your databases since there are much more of them now. When you set up a lab farm you typically run Products Configuration Wizard which leaves you with several databases created whose names contain GUIDs, which makes it hard to distinguish between them and relate them to corresponding farms. &lt;/p&gt;&lt;p&gt;Let’s say you need to get rid of a farm and want to delete corresponding databases after. What do you do? If you haven’t yet disconnected from the farm and uninstalled SharePoint then PowerShell comes at help. Log in to one of the farm servers, start up SharePoint 2010 Management Shell and enter this command:&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;&lt;strong&gt;Get-SPDatabase | % {$_.Name}&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;It will list names of all databases utilized in the current farm. You can now create a script to drop these databases or do whatever you needed to do with them. If however it is too late and you have uninstalled your servers, you can still get the list of database names using a SQL query:&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;USE SharePoint_Config&lt;br /&gt;select distinct name from Objects WITH(NOLOCK) where Name in (&lt;br /&gt;select Name COLLATE Latin1_General_CI_AS_KS_WS from sys.databases WITH(NOLOCK))&lt;br /&gt;GO&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Replace &lt;strong&gt;SharePoint_Config &lt;/strong&gt;with the name of configuration database for your farm. SharePoint products use &lt;strong&gt;Latin1_General_CI_AS_KS_WS&lt;/strong&gt; collation so you need to do a cast. It is of course not supported to issue queries directly against SQL Server so I would use this approach for development environment only, and only when you are really cleaning it up and PowerShell isn’t an option.&lt;/p&gt;&lt;p&gt;Alternatively to avoid the mess in your database names from the start you can also pre-create them. &lt;a title="Deploy by using DBA-created databases (SharePoint Server 2010)" href="http://technet.microsoft.com/en-us/library/cc262869.aspx" target="_blank"&gt;Here is the guidance&lt;/a&gt;. Lastly, although the guidance does not suggest sharing database role between farms in production environment, it is quite practical to share a SQL server in development environment if you are not using your farm for performance and capacity testing.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;UPDATE:&lt;/strong&gt; on technet there is a list of databases used by SharePoint (a section in storage and SQL Server capacity planning article): &lt;a href="http://technet.microsoft.com/en-us/library/cc298801.aspx#section1a"&gt;http://technet.microsoft.com/en-us/library/cc298801.aspx#section1a&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7384653670825187633-4254719022483682291?l=neganov.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://neganov.blogspot.com/2010/09/enumerate-sharepoint-2010-databases.html</link><author>noreply@blogger.com (Ivan Neganov)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7384653670825187633.post-7534873084698528230</guid><pubDate>Mon, 30 Aug 2010 11:34:00 +0000</pubDate><atom:updated>2010-08-30T04:34:07.074-07:00</atom:updated><title>Slipstreamed Installation of SharePoint Server 2010 with June 2010 CU</title><description>&lt;p&gt;I wanted to create a slipstreamed installation point for SharePoint Server 2010, which would include &lt;a title="Stefan Goßner: The first cumulative update for SharePoint 2010 family has been released" href="http://blogs.technet.com/b/stefan_gossner/archive/2010/07/22/the-first-cumulative-update-for-sharepoint-2010-family-has-been-released.aspx" target="_blank"&gt;June 2010 CU&lt;/a&gt;. I could not find guidance on how to do this for the current version. &lt;a title="Create an installation source that includes software updates (Office SharePoint Server 2007)" href="http://technet.microsoft.com/en-us/library/cc261890(office.12).aspx" target="_blank"&gt;MOSS 2007 guidance&lt;/a&gt; recommends extracting patches into &lt;strong&gt;\Update&lt;/strong&gt; folder of the installation point. This works as well for the SharePoint 2010. Would the installer also pick up and apply executable packages, or&amp;#160; their extracts in subfolders under the &lt;strong&gt;\Update&lt;/strong&gt;? I tried both variants – it does not. &lt;/p&gt;  &lt;p&gt;The reason I went that path was because June 2010 CU consists of 6 packages, which is unusual given regular MOSS CUs single file format. Also when extracting each of the patches manually to a common folder the following two files are duplicated between &lt;a title="KB983319" href="http://support.microsoft.com/default.aspx?scid=kb;EN-US;983319" target="_blank"&gt;KB983319&lt;/a&gt; and &lt;a title="KB983497" href="http://support.microsoft.com/default.aspx?scid=kb;EN-US;983497" target="_blank"&gt;KB983497&lt;/a&gt; patches: &lt;strong&gt;osrchwfe-x-none.msp, osrchwfe-x-none.xml&lt;/strong&gt;; and the following two - between &lt;a title="KB2281364" href="http://support.microsoft.com/default.aspx?scid=kb;EN-US;2281364" target="_blank"&gt;KB2281364&lt;/a&gt; and &lt;a title="KB983497" href="http://support.microsoft.com/default.aspx?scid=kb;EN-US;983497" target="_blank"&gt;KB983497&lt;/a&gt;: &lt;strong&gt;pplwfe-x-none.msp, pplwfe-x-none.xml&lt;/strong&gt;. By reviewing KB articles it appears that the files are identical so it is ok to overwrite them, which is what I’ve done using a script:&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;office-kb2124512-fullfile-x86-glb.exe /extract:C:\temp\sharepoint\Updates     &lt;br /&gt;office-kb2204024-fullfile-x64-glb.exe /extract:C:\temp\sharepoint\Updates      &lt;br /&gt;office-kb2281364-fullfile-x64-glb.exe /extract:C:\temp\sharepoint\Updates      &lt;br /&gt;office-kb983319-fullfile-x64-glb.exe /extract:C:\temp\sharepoint\Updates      &lt;br /&gt;office-kb983497-fullfile-x64-glb.exe /extract:C:\temp\sharepoint\Updates      &lt;br /&gt;spf-kb2028568-fullfile-x64-glb.exe /extract:C:\temp\sharepoint\Updates&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;Next I copied extracted files to the &lt;strong&gt;\Updates &lt;/strong&gt;folder in my installation point.&lt;/p&gt;  &lt;p&gt;After installing SharePoint and running configuration wizard most of the patches were applied, except for &lt;a title="KB2124512" href="http://support.microsoft.com/default.aspx?scid=kb;EN-US;2124512" target="_blank"&gt;KB2124512&lt;/a&gt; and &lt;a title="KB2204024" href="http://support.microsoft.com/default.aspx?scid=kb;EN-US;2204024" target="_blank"&gt;KB2204024&lt;/a&gt; according to DLL version check. I am running Windows 2008 R2, and SQL Server 2008 R2, and made a farm installation of SharePoint. It could be that either these patches do not apply in my environment, or something is not working in my installation. I will post an update if I find out more. For now I consider that the slipstream approach is generally the same as before even for multi-file CUs such as this one.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7384653670825187633-7534873084698528230?l=neganov.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://neganov.blogspot.com/2010/08/slipstreamed-installation-of-sharepoint.html</link><author>noreply@blogger.com (Ivan Neganov)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7384653670825187633.post-7925214854131104247</guid><pubDate>Fri, 28 May 2010 05:19:00 +0000</pubDate><atom:updated>2010-07-20T08:43:02.984-07:00</atom:updated><title>Modified Date Field is not Visible after Content Deployment</title><description>&lt;p&gt;It is the simple things, or at least ones you assume must be simple that often create some extra anxiety with SharePoint – at least from what I’ve seen. Here is one I ran into a couple of days ago: my customer runs a SharePoint 2007 publishing portal with February 2010 CU, where content is created in authoring environment, then content deployment job transfers it to production farm located in perimeter zone and accessible to anonymous Internet users. The application is using a significant amount of custom code. In many cases SharePoint API is used as a data provider, and is accessed through an adapter layer, which helps decoupling custom code from the platform. Quite logical. &lt;/p&gt;&lt;p&gt;An example of how the adapter accesses SharePoint API is retrieving SharePoint document library information through &lt;strong&gt;SPList.GetItems(SPQuery).GetDataTable().&lt;/strong&gt; The &lt;strong&gt;DataTable&lt;/strong&gt; instance is then returned back to the consuming custom code. The problem is that Modified column is missing from the returned &lt;strong&gt;DataTable&lt;/strong&gt; in production farm, while it is there in authoring farm, which certainly breaks a lot of application logic.&lt;/p&gt;&lt;p&gt;It turns out that a Content Deployment Job Path setting (Central Administration &amp;gt; Operations &amp;gt; Manage Content Deployment Paths and Jobs &amp;gt; Content Deployment Path) is to blame: &lt;strong&gt;Security Information &lt;/strong&gt;must be set to &lt;strong&gt;All &lt;/strong&gt;in order for the issue to go away, and you would need to re-create the target site collection. Now this will not be a completely painless move – you will start getting a content deployment warning: &lt;strong&gt;User security information cannot be properly imported without setting UserInfoDateTime option to ImportAll.&lt;/strong&gt; This is because you have a &lt;strong&gt;Deploy User Names&lt;/strong&gt; checkbox cleared, which you should according to the &lt;a href="http://technet.microsoft.com/en-us/library/cc263468(office.12).aspx" target="_blank"&gt;guidance&lt;/a&gt;. Here is a related &lt;a href="http://murmurofawebmaster.blogspot.com/2008/07/user-security-information-cannot-be.html" target="_blank"&gt;post&lt;/a&gt; about this warning. &lt;/p&gt;&lt;p&gt;What actually happens is when &lt;strong&gt;Security Information &lt;/strong&gt;is not set to &lt;strong&gt;All&lt;/strong&gt;, this results in hiding certain fields, including &lt;strong&gt;Modified &lt;/strong&gt;date field. So the &lt;strong&gt;GetItems(SPQuery) &lt;/strong&gt;will still return correct items satisfying the &lt;strong&gt;SPQuery&lt;/strong&gt; parameter, but if you inspect properties of an &lt;strong&gt;SPField&lt;/strong&gt; for the returned items you will see that:&lt;/p&gt;&lt;pre class="csharpcode"&gt; item.Fields[&lt;span class="str"&gt;"Modified"&lt;/span&gt;].CanToggleHidden == &lt;span class="kwrd"&gt;false&lt;/span&gt;;&lt;br /&gt; item.Fields[&lt;span class="str"&gt;"Modified"&lt;/span&gt;].Hidden == &lt;span class="kwrd"&gt;true&lt;/span&gt;;&lt;/pre&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre&lt;br /&gt;{&lt;br /&gt; font-size: small;&lt;br /&gt; color: black;&lt;br /&gt; font-family: consolas, "Courier New", courier, monospace;&lt;br /&gt; background-color: #ffffff;&lt;br /&gt; /*white-space: pre;*/&lt;br /&gt;}&lt;br /&gt;.csharpcode pre { margin: 0em; }&lt;br /&gt;.csharpcode .rem { color: #008000; }&lt;br /&gt;.csharpcode .kwrd { color: #0000ff; }&lt;br /&gt;.csharpcode .str { color: #006080; }&lt;br /&gt;.csharpcode .op { color: #0000c0; }&lt;br /&gt;.csharpcode .preproc { color: #cc6633; }&lt;br /&gt;.csharpcode .asp { background-color: #ffff00; }&lt;br /&gt;.csharpcode .html { color: #800000; }&lt;br /&gt;.csharpcode .attr { color: #ff0000; }&lt;br /&gt;.csharpcode .alt&lt;br /&gt;{&lt;br /&gt; background-color: #f4f4f4;&lt;br /&gt; width: 100%;&lt;br /&gt; margin: 0em;&lt;br /&gt;}&lt;br /&gt;.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;br /&gt;&lt;p&gt;and the &lt;strong&gt;SPListItemCollection.GetDataTable() &lt;/strong&gt;method omits hidden fields when it constructs the &lt;strong&gt;DataTable&lt;/strong&gt;. Knowing the above you can either edit content deployment path and do a clean content deployment, or if it is problematic for some reason, then you can change your custom code to manually construct a &lt;strong&gt;DataTable&lt;/strong&gt; rather than using &lt;strong&gt;SPListItemCollection.GetDataTable()&lt;/strong&gt;.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;span style="color:#ff0000;"&gt;UPDATE:&lt;/span&gt;&lt;/strong&gt; The issue was fixed in April Cumulative Update (see &lt;a href="http://support.microsoft.com/kb/981040/"&gt;http://support.microsoft.com/kb/981040/&lt;/a&gt; for more details). Thanks to Bill Brockbank for noting this. A good moment to emphasize importance of running up-to-date software.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7384653670825187633-7925214854131104247?l=neganov.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://neganov.blogspot.com/2010/05/modified-field-is-not-visible-after.html</link><author>noreply@blogger.com (Ivan Neganov)</author><thr:total>1</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7384653670825187633.post-5020560805110589123</guid><pubDate>Thu, 29 Apr 2010 17:53:00 +0000</pubDate><atom:updated>2010-04-29T11:07:25.410-07:00</atom:updated><title>Records Management in SharePoint 2010</title><description>SharePoint 2010 has a lot more to offer in records management space than its predecessor. &lt;a href="http://www.khamis.net/"&gt;Rez&lt;/a&gt; will be presenting at Mississauga SharePoint User Group on May 4th. The topic is &lt;a href="http://www.khamis.net/blog/Lists/Posts/Post.aspx?ID=26"&gt;SharePoint 2010 Records Management Features&lt;/a&gt;. Rez has many years of experience with SharePoint and deep knowledge of the technology. I look forward to and highly recommend next week's session.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7384653670825187633-5020560805110589123?l=neganov.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://neganov.blogspot.com/2010/04/records-management-in-sharepoint-2010.html</link><author>noreply@blogger.com (Ivan Neganov)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7384653670825187633.post-6520946857804661579</guid><pubDate>Thu, 22 Apr 2010 06:01:00 +0000</pubDate><atom:updated>2010-04-25T20:53:28.063-07:00</atom:updated><title>Toronto SharePoint User Group Meeting Follow Up</title><description>Thanks for coming out to the April 21 TSPUG meeting, I was excited to talk about performance once again, and hope you have found the meeting useful. As you can see from my blog, I have done the same talk a month earlier at Toronto SharePoint Camp, and the decks are pretty much identical, the difference being that yesterday I had enough time to do decent demos on load testing. If you are interested in material from the slides or need a reference to one of the resources listed there, just use &lt;a href="http://www.softforte.com/Resources/PlanningAndMeasuringPerformanceOfASharePointFarm.pptx"&gt;my deck from the camp&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7384653670825187633-6520946857804661579?l=neganov.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://neganov.blogspot.com/2010/04/toronto-sharepoint-user-group-meeting.html</link><author>noreply@blogger.com (Ivan Neganov)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7384653670825187633.post-4239555580229170674</guid><pubDate>Sun, 21 Mar 2010 15:27:00 +0000</pubDate><atom:updated>2010-03-21T08:27:37.344-07:00</atom:updated><title>Toronto SharePoint Camp 2010</title><description>&lt;p&gt;It was my second time when I took part in the event, and it was fun again. Great thanks to Eli, Bill, Ruven, Kanwal, Graham and other people&amp;#160; who organized it. Thanks to the folks who showed up and dedicated their Saturday to SharePoint! &lt;a title="SoftForte - the Science of Quality" href="http://www.softforte.com" target="_blank"&gt;SoftForte&lt;/a&gt; was the gold sponsor of the event.&lt;/p&gt;  &lt;p&gt;For those interested in references and links related to my presentation “Planning and Measuring Performance of a SharePoint Farm”, &lt;a title="Planning and Measuring Performance of a SharePoint Farm" href="http://www.softforte.com/Resources/PlanningAndMeasuringPerformanceOfASharePointFarm.pptx"&gt;the deck is available for download&lt;/a&gt;. It will also soon be available from the &lt;a title="Toronto SharePoint Camp" href="http://www.torontosharepointcamp.com/Pages/Default.aspx" target="_blank"&gt;SharePoint camp site&lt;/a&gt;. &lt;/p&gt;  &lt;p&gt;Due to time constraint at the camp I’ve excluded some details and the entire topic on performance tuning best practices from my talk, but I left these slides in downloadable version of the deck as this is all useful information and contains many good references.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7384653670825187633-4239555580229170674?l=neganov.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://neganov.blogspot.com/2010/03/toronto-sharepoint-camp-2010.html</link><author>noreply@blogger.com (Ivan Neganov)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7384653670825187633.post-762731509477789534</guid><pubDate>Thu, 14 Jan 2010 18:30:00 +0000</pubDate><atom:updated>2010-01-14T10:41:02.448-08:00</atom:updated><title>Stand-Alone Network Emulator for VS2010 Beta 2</title><description>&lt;p&gt;At the “Load Testing SharePoint 2010 with VSTT” presentation at &lt;a title="SPC 2009" href="http://www.mssharepointconference.com/pages/default.aspx" target="_blank"&gt;SPC 2009&lt;/a&gt; I’ve learned about the new network emulator, allowing one to model various network latencies and bandwidth values. The emulator is available as a part of Visual Studio 2010. I’ve got excited, and found the following two great blog posts by Lonny Kruger, &lt;a title="Introducing True Network Emulation in Visual Studio 2010" href="http://blogs.msdn.com/lkruger/archive/2009/06/08/introducing-true-network-emulation-in-visual-studio-2010.aspx" target="_blank"&gt;first one describing how to enable the emulator through the VS2010&lt;/a&gt;, and &lt;a title="Creating a Stand-Alone Network Emulator using VS2010 – Beta 1 Release" href="http://blogs.msdn.com/lkruger/archive/2009/06/24/creating-a-stand-alone-network-emulator-using-vs2010-beta-1-release.aspx" target="_blank"&gt;the second one – how to write a stand-alone emulator&lt;/a&gt;, which would rely on VS2010 API but not require running a load test to simulate specific network characteristics. Also for reference, here is an MSDN page on the topic: &lt;a title="http://msdn.microsoft.com/en-us/library/dd505008(VS.100).aspx" href="http://msdn.microsoft.com/en-us/library/dd505008(VS.100).aspx"&gt;http://msdn.microsoft.com/en-us/library/dd505008(VS.100).aspx&lt;/a&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;The only problem was – these 2 blog posts were for the Beta 1 release of Visual Studio 2010, while I already had the Beta 2, and some changes were made in the Beta 2, that are worth to note here. I have written a stand-alone emulator using Lonny’s post as a starting point, but changing a few things to get it working with the Beta 2. The tool can be downloaded &lt;a title="Network Emulator for Visual Studio 2010 Beta 2.zip" href="http://www.softforte.com/resources/Network%20Emulator%20for%20Visual%20Studio%202010%20Beta%202.zip" target="_blank"&gt;here&lt;/a&gt;, and its source code - &lt;a title="Network Emulator for Visual Studio 2010 Beta 2.src.zip" href="http://www.softforte.com/resources/Network%20Emulator%20for%20Visual%20Studio%202010%20Beta%202.src.zip" target="_blank"&gt;here&lt;/a&gt;. Below is a list of pre-requisites to get the emulation tool running, and description of what and why I have changed compared to Lonny’s original post. I recommend reading his two posts first to get a better context.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;u&gt;Pre-Requisites&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;You would need Visual Studio 2010 Beta 2 installed in order to run the emulator. I’ve tested the tool with VS2010 Beta 2 Ultimate Edition on a 64-bit Windows 7 box. You would also need .NET Framework 4.0, which is installed by default when you install the Visual Studio. Once you have that, you need to install network emulation driver. This is done one time only through the Visual Studio UI. From that point on, you don’t need to start Visual Studio to run the stand-alone emulator.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;u&gt;Enabling the Driver&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;The driver is accessed via a Test Settings dialog. You need to create test settings first. One way to do it is to create a new Test Project: File &amp;gt;&amp;gt; New Project… &amp;gt;&amp;gt; Test Project. Below is a screen shot of a project type selector dialog.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_uLvQGkZ2Z10/S09izqJs4_I/AAAAAAAAACA/d1v95PRRHGI/s1600-h/image%5B8%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/_uLvQGkZ2Z10/S09i0BufvbI/AAAAAAAAACE/X2XKTJCt1yA/image_thumb%5B4%5D.png?imgmax=800" width="366" height="247" /&gt;&lt;/a&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Once you have a test project, you can double-click on the &lt;strong&gt;Local.testsettings &lt;/strong&gt;solution item in Solution Explorer to bring up the Test Settings dialog, then enable Network Emulation as shown on the following screen shot:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_uLvQGkZ2Z10/S09i0tpiJFI/AAAAAAAAACY/7-piJDfP8GU/s1600-h/Enabling%20Emulation%5B5%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="Enabling Emulation" border="0" alt="Enabling Emulation" src="http://lh5.ggpht.com/_uLvQGkZ2Z10/S09i1JC9vwI/AAAAAAAAACc/QeCEP9A4alo/Enabling%20Emulation_thumb%5B3%5D.png?imgmax=800" width="717" height="445" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Lastly, to enable the driver click on Configure button for selected and checked Network Emulation. Follow the prompts asking to confirm the driver installation:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_uLvQGkZ2Z10/S09i1gTbgUI/AAAAAAAAACo/sLeJRQeqDHE/s1600-h/Installing%20Driver%5B4%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="Installing Driver" border="0" alt="Installing Driver" src="http://lh3.ggpht.com/_uLvQGkZ2Z10/S09i2M9zu5I/AAAAAAAAACs/TPzgCwdfL5Q/Installing%20Driver_thumb%5B2%5D.png?imgmax=800" width="717" height="438" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;You can now use the network emulator as a part of Visual Studio for web performance and load tests, or close Visual Studio and use the stand-alone tool, for which you need administrator’s rights.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;u&gt;Stand-Alone Network Emulator Source Code&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;I started off by copying Lonny’s sample code, except that I use a WPF application as opposed to WinForms. Once I built and ran it, I kept getting negative long values returned through interop from the &lt;strong&gt;NativeNetworkEmulationAPI &lt;/strong&gt;class, which is listed in Lonny’s post. Tried running the program as administrator – still same errors. So using reflector I inspected the Visual Studio network emulation classes, and found this type, which appears to serve the same purpose as the NativeNetworkEmulationAPI: &lt;strong&gt;Microsoft.VisualStudio.QualityTools.NetworkEmulation.NetworkEmulationDriver&lt;/strong&gt;. All I needed to do was to change method calls to use this class instead of the NativeNetworkEmulationAPI.&lt;/p&gt;  &lt;p&gt;Regarding the network profiles, you have to edit these XML files following &lt;a title="Creating a Stand-Alone Network Emulator using VS2010 – Beta 1 Release" href="http://blogs.msdn.com/lkruger/archive/2009/06/24/creating-a-stand-alone-network-emulator-using-vs2010-beta-1-release.aspx" target="_blank"&gt;Lonny’s instructions&lt;/a&gt; to make them work. If you simply use the OOTB profiles, you will not get an error, but the emulation won’t start. I have copied and changed the default network profiles, so you only need to do this if you want to add a new custom profile, in which case just place the profile XML file into Profiles sub-folder and re-start the emulator.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7384653670825187633-762731509477789534?l=neganov.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://neganov.blogspot.com/2010/01/stand-alone-network-emulator-for-vs2010.html</link><author>noreply@blogger.com (Ivan Neganov)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh3.ggpht.com/_uLvQGkZ2Z10/S09i0BufvbI/AAAAAAAAACE/X2XKTJCt1yA/s72-c/image_thumb%5B4%5D.png?imgmax=800" height="72" width="72" /><thr:total>2</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7384653670825187633.post-4441272563933899435</guid><pubDate>Wed, 13 Jan 2010 14:06:00 +0000</pubDate><atom:updated>2010-01-13T06:06:35.591-08:00</atom:updated><title>Presentation Deck from January 12 MSPUG Meeting</title><description>&lt;p&gt;I wanted to thank people who showed up at yesterday’s Mississauga SharePoint User Group meeting. Also thanks Ray for organizing and Peter for sponsoring it. I think it was a great evening. &lt;/p&gt;  &lt;p&gt;Peter’s part of presentation was exciting. Not only he is a good speaker, but &lt;a href="http://www.envisionit.com" target="_blank"&gt;Envision IT&lt;/a&gt; also has done some great work. Even though I have got through about 40% of what I wanted to cover in my part of presentation before I ran out of time, I hope it was interesting and useful. You can download my deck &lt;a title="Planning and Measuring Performance of a SharePoint Farm - Part 1" href="http://www.softforte.com/resources/Planning%20and%20Measuring%20Performance%20of%20a%20SharePoint%20Farm%20-%20Part%201.pdf" target="_blank"&gt;here&lt;/a&gt;. Also according to Ray it will be available at some point on the &lt;a href="http://www.mspug.ca/default.aspx" target="_blank"&gt;MSPUG&lt;/a&gt; site.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7384653670825187633-4441272563933899435?l=neganov.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://neganov.blogspot.com/2010/01/presentation-deck-from-january-12-mspug.html</link><author>noreply@blogger.com (Ivan Neganov)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7384653670825187633.post-6140747178376651248</guid><pubDate>Thu, 07 Jan 2010 16:55:00 +0000</pubDate><atom:updated>2010-01-07T09:20:25.789-08:00</atom:updated><title>Dynamic Text Highlighting with jQuery</title><description>&lt;p&gt;I’ve got my hands dirty with jQuery once again, creating animated text line with dynamic highlighting of its letters. As usual I started by looking for existing plug-ins – didn’t find quite what I needed, so I wrote my own animation. It is possible that there are ones that I just missed, but thanks to jQuery my own animation ended up being pretty simple, which I want to illustrate here.&lt;/p&gt;  &lt;p&gt;I was dynamically writing out letters and changing their &lt;strong&gt;font-weight&lt;/strong&gt; CSS property to create the effect of highlighting. I think it worked out nicely. It even works on my iPhone 3G. You can see the page &lt;a href="http://www.softforte.com" target="_blank"&gt;here&lt;/a&gt;. Below are a couple of notes on its source code:&lt;/p&gt;  &lt;p&gt;It starts with displaying a semi-transparent banner by using jQuery &lt;strong&gt;animate &lt;/strong&gt;function to change its &lt;strong&gt;left &lt;/strong&gt;CSS property. The banner (id=”motto”) is clipped by a surrounding div (id=”mottoclip”), which creates the perception of it appearing out of nothing rather than simply sliding horizontally. With jQuery it is as simple as this:&lt;/p&gt;  &lt;div id="codeSnippetWrapper"&gt;   &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;$(&lt;span style="color: #006080"&gt;&amp;quot;#motto&amp;quot;&lt;/span&gt;).animate(&lt;br /&gt;    { left: &lt;span style="color: #006080"&gt;&amp;quot;2px&amp;quot;&lt;/span&gt; },&lt;br /&gt;    { duration: rolloverDuration, easing: &lt;span style="color: #006080"&gt;&amp;quot;linear&amp;quot;&lt;/span&gt;, complete: showMotto });&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Once the banner is in place the &lt;strong&gt;showMotto()&lt;/strong&gt; callback function sets up a recursive output of the letters. The recursion is implemented in &lt;strong&gt;writeText()&lt;/strong&gt; function. It outputs the motto line of text one letter per recursion, setting timeout between them. In order to be able to “highlight” a letter, it needs to be placed in its own span. The letter becomes visible once its span is added to the parent container through jQuery &lt;strong&gt;append()&lt;/strong&gt; method: &lt;/div&gt;&lt;br /&gt;  &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;span style="color: #0000ff"&gt;var&lt;/span&gt; characterSpan = &lt;span style="color: #006080"&gt;&amp;quot;&amp;lt;span id='mt&amp;quot;&lt;/span&gt; + i + &lt;span style="color: #006080"&gt;&amp;quot;'&amp;gt;&amp;quot;&lt;/span&gt; + character + &lt;span style="color: #006080"&gt;&amp;quot;&amp;lt;/span&amp;gt;&amp;quot;&lt;/span&gt;;&lt;br /&gt;container.append(characterSpan);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Then we construct a jQuery selector object for each character, so that we can easily animate it. Next, call a function &lt;strong&gt;animateLetter()&lt;/strong&gt; where we first hide letter completely, then gradualy show it in bold (font-weight: 700), then return to normal (font-weight: 400):&lt;br /&gt;&lt;br /&gt;  &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;span style="color: #0000ff"&gt;function&lt;/span&gt; animateLetter(jChar, letterShowTimeout, letterResetTimeout)&lt;br /&gt;{&lt;br /&gt;    jChar.hide();&lt;br /&gt;    jChar.css(&lt;span style="color: #006080"&gt;&amp;quot;display&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;inline&amp;quot;&lt;/span&gt;);&lt;br /&gt;    jChar.css(&lt;span style="color: #006080"&gt;&amp;quot;font-weight&amp;quot;&lt;/span&gt;, 400);&lt;br /&gt;    jChar.show(letterShowTimeout, &lt;span style="color: #0000ff"&gt;function&lt;/span&gt;() { jChar.css(&lt;span style="color: #006080"&gt;&amp;quot;font-weight&amp;quot;&lt;/span&gt;, 700); });&lt;br /&gt;    setTimeout(&lt;span style="color: #0000ff"&gt;function&lt;/span&gt;() { jChar.css(&lt;span style="color: #006080"&gt;&amp;quot;font-weight&amp;quot;&lt;/span&gt;, 400); }, letterResetTimeout);&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;At this point we move on to writing out and animating the next letter, and so on. &lt;br /&gt;&lt;br /&gt;Lastly there is an “artistic touch” on all this – the easing. Easing determines how an animation ends to create a pleasant visual effect. You’ve probably seen menu fly-outs that appear to oscillate slightly at the end of their path, or they simply slow down, etc. By the way one great example of this can be seen in &lt;a title="jQuery Scrollable" href="http://flowplayer.org/tools/scrollable.html" target="_blank"&gt;jQuery Scrollable control&lt;/a&gt;.&lt;br /&gt;&lt;p&gt;In my case easing was implemented starting at 14th character of the motto text. From that point the timeout between displaying letters increased exponentially, and timeout between making each letter bold and resetting it back to normal – linearly with each iteration:&lt;br /&gt;&lt;br /&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;span style="color: #0000ff"&gt;var&lt;/span&gt; letterShowTimeout = 60;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;var&lt;/span&gt; letterResetTimeout = 90;&lt;br /&gt;&lt;span style="color: #0000ff"&gt;var&lt;/span&gt; easingStartLength = 14;&lt;br /&gt; &lt;br /&gt;&lt;span style="color: #0000ff"&gt;if&lt;/span&gt; ( i &amp;gt; easingStartLength ) &lt;br /&gt;{&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;var&lt;/span&gt; easing = Math.ceil((i - easingStartLength) / 3);&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;var&lt;/span&gt; easingSq = easing * easing;&lt;br /&gt;    letterShowTimeout += easingSq * letterShowTimeout;&lt;br /&gt;    letterResetTimeout += easing * letterResetTimeout;&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt; If you think of the animation as of lighting up a string of text with a flashlight, the easing creates an effect of the light spot getting wider towards the end. And yes, all the constants and exponents are empirical. If you want to use something similar, you’ve got to experiment with numbers.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7384653670825187633-6140747178376651248?l=neganov.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://neganov.blogspot.com/2010/01/dynamic-text-highlighting-with-jquery.html</link><author>noreply@blogger.com (Ivan Neganov)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7384653670825187633.post-996483086534421629</guid><pubDate>Thu, 24 Dec 2009 04:59:00 +0000</pubDate><atom:updated>2009-12-23T21:15:49.633-08:00</atom:updated><title>SharePoint Best Practices Analyzer Rules</title><description>&lt;p&gt;I needed to extract the list of default best practices from the &lt;a title="Microsoft Best Practices Analyzer for Windows SharePoint Services 3.0 and the 2007 Microsoft Office System" href="http://www.microsoft.com/downloads/details.aspx?familyid=cb944b27-9d6b-4a1f-b3e1-778efda07df8&amp;amp;displaylang=en" target="_blank"&gt;Microsoft Best Practices Analyzer for Windows SharePoint Services 3.0 and the 2007 Microsoft Office System&lt;/a&gt;. The best practices are encoded as rules in the tool’s XML configuration file. Bill Baer has a great &lt;a title="Bill Baer&amp;#39;s blog post on understanding SharePoint BPA configuration file" href="http://blogs.technet.com/wbaer/archive/2007/04/17/understanding-the-microsoft-best-practices-analyzer-for-windows-sharepoint-services-3-0-and-the-2007-microsoft-office-system-rule-file.aspx" target="_blank"&gt;blog post&lt;/a&gt; discussing it as well as how to add custom rules for the tool to check. So you can see the rules’ titles and explanations by inspecting this file, except that it is pretty hard to read. &lt;/p&gt;  &lt;p&gt;When you run the tool, it first downloads an update to its configuration file then goes on checking the rules. I found it easiest to update the configuration file then write a little XML parser and dump each default rule’s title, category and description into an Excel file.&amp;#160; You can download it &lt;a title="SharePoint Best Practices Analyzer Rules" href="http://www.neganov.com/blogspotfiles/SharePointBpaRules.xls"&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7384653670825187633-996483086534421629?l=neganov.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://neganov.blogspot.com/2009/12/sharepoint-best-practices-analyzer.html</link><author>noreply@blogger.com (Ivan Neganov)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7384653670825187633.post-1184092743227771992</guid><pubDate>Thu, 19 Nov 2009 21:32:00 +0000</pubDate><atom:updated>2009-11-19T13:34:58.593-08:00</atom:updated><title>Cannot Edit SharePoint 2007 List in Datasheet after Office 2010 Beta is Installed</title><description>&lt;p&gt;I couldn’t wait to set up the Office 2010 beta, which became available this Monday. One interesting issue I’ve ran into was this:&lt;/p&gt;  &lt;p&gt;1. I installed 64-bit version of Office 2010 Professional Plus beta (en_office_professional_plus_2010_beta_x64_x16-19234.exe version 14.0.4536.1000) on a Windows 7 box. I was forced&amp;#160; to uninstall Office 2007 Ultimate I had there before in order to proceed with the 2010 setup.&lt;/p&gt;  &lt;p&gt;2. Today I went to my SharePoint 2007 intranet site and attempted to edit a custom list in datasheet view. I’ve got an error “The list cannot be displayed in Datasheet view…”:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_uLvQGkZ2Z10/SwW5PXB-XTI/AAAAAAAAABg/LE6a5fEXHWQ/s1600-h/image%5B1%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/_uLvQGkZ2Z10/SwW5PjiofUI/AAAAAAAAABk/vDMWqVinjC4/image_thumb.png?imgmax=800" /&gt;&lt;/a&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;It turned out that IE 8 zone security was fine – I was missing ActiveX component necessary for datasheet editing, the &lt;a title="ListNet ActiveX control on MSDN" href="http://msdn.microsoft.com/en-us/library/ms416795.aspx"&gt;ListNet Control&lt;/a&gt;. This control is packaged inside STSLIST.DLL library. The library was deployed to %ProgramFiles%\Microsoft Office\Office14 directory, but wasn’t registered as a COM server, which resulted in failure of JavaScript on SharePoint page to create an instance of the corresponding ActiveX control for the &lt;strong&gt;ListNet.ListNet&lt;/strong&gt; progID. &lt;/p&gt;  &lt;p&gt;Various editions of Microsoft Office 2007 include SharePoint support component, which is installed by default: &lt;strong&gt;Microsoft Office &amp;gt;&amp;gt; Office Tools &amp;gt;&amp;gt; Windows SharePoint Services Support&lt;/strong&gt;. Specifically the “Edit in datasheet” feature is supported by the sub-component named “Microsoft Office Access Web Datasheet Component”. I went and checked out the components installed for my Office 2010 – and the analogous components were marked as installed: &lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_uLvQGkZ2Z10/SwW5QL1cEjI/AAAAAAAAABo/_Gj8EIBNiX8/s1600-h/image12.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/_uLvQGkZ2Z10/SwW5Q_AyoxI/AAAAAAAAABs/vVu_IcL2Y2M/image_thumb8.png?imgmax=800" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Now that appears to be an issue. It would be interesting to know if anyone else ran into the same situation or was it just me. The workaround was easy – install back Windows SharePoint Services Support for Office 2007. Below is a screenshot – I only needed this specific part of the office and nothing else:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_uLvQGkZ2Z10/SwW5RxMoBuI/AAAAAAAAABw/MGxatj_AzhU/s1600-h/Install3.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Install" border="0" alt="Install" src="http://lh4.ggpht.com/_uLvQGkZ2Z10/SwW5Sku00SI/AAAAAAAAAB0/Qb1MGD3o7a4/Install_thumb1.png?imgmax=800" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Now the “View in datasheet” worked for me. Interestingly, it appears as that both Office 12 and Office 14 versions got registered as a result. Here is the view at the COM object registry settings using oleview.exe tool (part of Visual Studio tools):&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_uLvQGkZ2Z10/SwW5TVL35fI/AAAAAAAAAB4/q-XVPbY7-ZQ/s1600-h/Oleview6.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Oleview" border="0" alt="Oleview" src="http://lh3.ggpht.com/_uLvQGkZ2Z10/SwW5VI_dXII/AAAAAAAAAB8/5hOrOj8wqW0/Oleview_thumb4.png?imgmax=800" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Hope this saves somebody time. Also here is a &lt;a title="List of MOSS 2007 ActiveX controls" href="http://blogs.technet.com/josebda/archive/2007/03/26/searching-the-visible-moss-2007-code-for-activex-references.aspx"&gt;link&lt;/a&gt; to a good post made by Jose Barreto, which lists all SharePoint 2007 ActiveX controls.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7384653670825187633-1184092743227771992?l=neganov.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://neganov.blogspot.com/2009/11/cannot-edit-sharepoint-2007-list-in.html</link><author>noreply@blogger.com (Ivan Neganov)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh4.ggpht.com/_uLvQGkZ2Z10/SwW5PjiofUI/AAAAAAAAABk/vDMWqVinjC4/s72-c/image_thumb.png?imgmax=800" height="72" width="72" /><thr:total>7</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7384653670825187633.post-7529802633573346494</guid><pubDate>Thu, 29 Oct 2009 14:22:00 +0000</pubDate><atom:updated>2009-10-29T07:36:59.825-07:00</atom:updated><title>SPC 2009</title><description>&lt;p&gt;It was a major event at a major venue. Organization was perfect: About 7500 attendees, most of whom were customers, enjoyed a total of ~300 hours of presentation material, over 40 hours of hands-on labs, were well fed and entertained (the 80s party night was a blast!). &lt;/p&gt;  &lt;p&gt;To me SPC 2009 was a great learning and networking opportunity. It was great to meet new people and to see people I have worked with in the past, including instructors and folks from SharePoint MCM3 rotation. Out of what I managed to attend, my favorites were both keynote presentations, business continuity management presentation by Doron Bar-Caspi and &lt;a href="http://blogs.technet.com/wbaer/"&gt;Bill Baer&lt;/a&gt;, and hands-on labs. &lt;/p&gt;  &lt;p&gt;Keynotes were done with superb quality, which definitely draws on art besides the knowledge. &lt;/p&gt;  &lt;p&gt;I enjoyed listening to Bill during MCM course, and during SPC he and Doron have delivered the best technical presentation out of the ones I’ve attended.&lt;/p&gt;  &lt;table border="0" cellspacing="0" cellpadding="2" width="627"&gt;&lt;tbody&gt;     &lt;tr&gt;       &lt;td valign="top" width="200"&gt;&lt;a href="http://lh4.ggpht.com/_uLvQGkZ2Z10/SumlNvqgWwI/AAAAAAAAABU/D0n59Y05rsY/s1600-h/SPC2009s%5B2%5D.jpg"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="SPC2009s" border="0" alt="SPC2009s" src="http://lh3.ggpht.com/_uLvQGkZ2Z10/SumlN3vWvYI/AAAAAAAAABc/2ju1ocB1ZiM/SPC2009s_thumb.jpg?imgmax=800" width="244" height="184" /&gt;&lt;/a&gt;&lt;/td&gt;        &lt;td valign="top" width="425"&gt;Hands-on labs helped me to quench my zest for playing with 2010 in the absence of Beta 2. In fact I’ve spent significant time in the lab knowing that recorded presentations would be available later. The lab room itself was impressive. The picture shows about 2/3 of it.         &lt;br /&gt;          &lt;br /&gt;Thanks to the SPC organizers! &lt;/td&gt;     &lt;/tr&gt;   &lt;/tbody&gt;&lt;/table&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7384653670825187633-7529802633573346494?l=neganov.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://neganov.blogspot.com/2009/10/spc-2009.html</link><author>noreply@blogger.com (Ivan Neganov)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh3.ggpht.com/_uLvQGkZ2Z10/SumlN3vWvYI/AAAAAAAAABc/2ju1ocB1ZiM/s72-c/SPC2009s_thumb.jpg?imgmax=800" height="72" width="72" /><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7384653670825187633.post-6009689632779555945</guid><pubDate>Fri, 31 Jul 2009 19:40:00 +0000</pubDate><atom:updated>2009-07-31T12:55:04.165-07:00</atom:updated><title>Software Estimation: Demystifying the Black Art</title><description>It was a mere curiosity that made me buy &lt;a href="http://www.amazon.com/Software-Estimation-Demystifying-Practices-Microsoft/dp/0735605351/ref=sr_1_1?ie=UTF8&amp;s=books&amp;qid=1249069524&amp;sr=8-1"&gt;this book&lt;/a&gt; - I didn't have a major project to estimate, I was finding the subject rather interesting especially having past experience observing various approaches and politics around software estimation. I was well rewarded for my interest - Steve McConnell delivered an easy, exciting and to the point reading experience once again. The book provides an excellent summary of decades of research in this important area, and is meticulously compiled and enforced by Steve's own expertise and opinion. More so the book is filled with practical advice and industry data, which makes it useful as a reference to get started estimating software THE PROPER WAY!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7384653670825187633-6009689632779555945?l=neganov.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://neganov.blogspot.com/2009/07/software-estimation-demystifying-black.html</link><author>noreply@blogger.com (Ivan Neganov)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7384653670825187633.post-5034519856541948598</guid><pubDate>Tue, 30 Jun 2009 12:01:00 +0000</pubDate><atom:updated>2009-06-30T23:46:23.987-07:00</atom:updated><title>Completed SharePoint MCM Training Rotation 3</title><description>&lt;p&gt;&lt;a href="http://download.microsoft.com/download/6/F/A/6FA23D13-3CAB-4FBD-81C8-0D92BB648DF3/MCM_MOSS_datasheet.pdf"&gt;SharePoint MCM certification&lt;/a&gt; is the topmost technical certification in Microsoft Office SharePoint Server 2007. A little over a week ago I have completed the 3-week training in Redmond. I have yet to get my certification though as I have passed only some of the exams. Fortunately there are retakes available so my challenge is still on. The SharePoint MCM certification training course had 3 exams, each at the end of the corresponding week, plus there was a full-day qualification lab on the very last day.&lt;/p&gt;  &lt;p&gt;Was the course useful? It was the most challenging training I have ever taken, it challenged my knowledge, time management skills and ability to keep up with 15 hour working days for 3 weeks. I was fortunate to meet with people who all were very solid SharePoint professionals already (we had 16 students in class), and learn from them. The course instructors were excellent, and also well-known names in SharePoint community. It was exciting to meet them in person with plenty of time for asking any level of depth of technical questions. Some of the course material was simply the best and hard to get anywhere else. Each student was provided with excellent hardware for doing labs. Most of us do not have that level of lab environment at work. And I definitely know much more about the product now, which by the way helps me being better prepared for working with its next version. Lastly, the exams were a challenge – I still have work to do there. So the experience was worth every dollar I’ve spent on it. I’d like to thank the organizers of the MCM training here, and especially James Petrosky who made this course a great experience for years to remember.&lt;/p&gt;  &lt;p&gt;I would recommend my colleagues in SharePoint community to go to this course since even during the weak economy the best investment you can make is into your knowledge. You won’t go bankrupt because of this! Even, and especially if you are seasoned, you would be surprised by how much more there is to learn about the product.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7384653670825187633-5034519856541948598?l=neganov.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://neganov.blogspot.com/2009/06/completed-sharepoint-mcm-training.html</link><author>noreply@blogger.com (Ivan Neganov)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7384653670825187633.post-6051783419612277574</guid><pubDate>Sun, 24 May 2009 09:52:00 +0000</pubDate><atom:updated>2009-05-24T03:32:19.511-07:00</atom:updated><title>jQuery on my Home Page</title><description>&lt;p&gt; &lt;/p&gt;&lt;p&gt;For a while I thought of adding some animation to &lt;a href="http://www.neganov.com/"&gt;my home page&lt;/a&gt; and so finally I got to doing it with help of &lt;a href="http://flowplayer.org/tools/scrollable.html"&gt;scrollable jQuery plugin&lt;/a&gt; from &lt;a href="http://flowplayer.org/"&gt;flowplayer.org&lt;/a&gt;. It is really easy compared with old reusable JavaScript components – standard indeed matters, plus great documentation on this particular plug-in made its integration very simple. Aside from some minor CSS work I had to add just a few lines of scripting code to make it all work:&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;&lt;pre style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; DIRECTION: ltr; BORDER-TOP-STYLE: none; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0pxfont-family:'Courier New', courier, monospace;font-size:8pt;color:black;" id="codeSnippet"   &gt;&amp;lt;&lt;span style="color:#0000ff;"&gt;script&lt;/span&gt; src=&lt;span style="color:#006080;"&gt;"http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style="color:#0000ff;"&gt;script&lt;/span&gt;&amp;gt;&lt;br /&gt;&amp;lt;&lt;span style="color:#0000ff;"&gt;script&lt;/span&gt; src=&lt;span style="color:#006080;"&gt;"styles/jquery.scrollable-1.0.2.min.js"&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style="color:#0000ff;"&gt;script&lt;/span&gt;&amp;gt;&lt;br /&gt;&amp;lt;&lt;span style="color:#0000ff;"&gt;script&lt;/span&gt; language=&lt;span style="color:#006080;"&gt;"javascript"&lt;/span&gt; type=&lt;span style="color:#006080;"&gt;"text/javascript"&lt;/span&gt;&amp;gt;&lt;br /&gt;    $(document).ready(&lt;span style="color:#0000ff;"&gt;function&lt;/span&gt;()&lt;br /&gt;    {&lt;br /&gt;        $(&lt;span style="color:#006080;"&gt;"div.scrollable"&lt;/span&gt;).scrollable({ size: 3 });&lt;br /&gt;    });&lt;br /&gt;&lt;br /&gt;    &lt;span style="color:#0000ff;"&gt;function&lt;/span&gt; moveNext()&lt;br /&gt;    {&lt;br /&gt;        $(&lt;span style="color:#006080;"&gt;"div.scrollable"&lt;/span&gt;).scrollable().next();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span style="color:#0000ff;"&gt;function&lt;/span&gt; movePrev()&lt;br /&gt;    {&lt;br /&gt;        $(&lt;span style="color:#006080;"&gt;"div.scrollable"&lt;/span&gt;).scrollable().prev();&lt;br /&gt;    }&lt;br /&gt;&amp;lt;/&lt;span style="color:#0000ff;"&gt;script&lt;/span&gt;&amp;gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7384653670825187633-6051783419612277574?l=neganov.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://neganov.blogspot.com/2009/05/jquery-on-my-home-page.html</link><author>noreply@blogger.com (Ivan Neganov)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7384653670825187633.post-2448280081456285365</guid><pubDate>Fri, 01 May 2009 04:34:00 +0000</pubDate><atom:updated>2009-04-30T21:41:40.191-07:00</atom:updated><title>Debugging SharePoint Timer Jobs</title><description>&lt;p&gt;When working on a SharePoint project recently I was faced with complexities related to development of SharePoint &lt;a href="http://www.andrewconnell.com/blog/archive/2007/01/10/5704.aspx"&gt;timer jobs&lt;/a&gt;, or more precisely – ones related to ensuring their proper quality. Indeed the timer jobs are not trivial when it gets to their debugging. Below is my approach to dealing with the issue:&lt;/p&gt;&lt;p&gt;1. First things first – you need to install your timer job, likely using a custom feature receiver. I am quoting Andrew Connell again, he has an excellent &lt;a href="http://www.andrewconnell.com/blog/articles/CreatingCustomSharePointTimerJobs.aspx"&gt;post&lt;/a&gt; describing the details.&lt;/p&gt;&lt;p&gt;2. You want to be able to start your timer job explicitly during testing (SharePoint does not let you do this other than through the  API). There are two obstacles here: &lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;- firstly you need the harness code to invoke the API, &lt;/p&gt;&lt;p&gt;- secondly you need to impersonate the identity of the Timer Service when invoking the API.&lt;/p&gt;&lt;p&gt;I have chosen to “abuse” the Unit Testing infrastructure given to me by Visual Studio to host my harness logic. You can either do the same or write a console application for this purpose. My unit test thus looked as follows:&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;&lt;pre style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; DIRECTION: ltr; BORDER-TOP-STYLE: none; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0pxfont-family:'Courier New', courier, monospace;font-size:8pt;color:black;" id="codeSnippet"   &gt;[TestClass]&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; TimerJobsTest&lt;br /&gt;{&lt;br /&gt;    &lt;span style="color:#0000ff;"&gt;private&lt;/span&gt; Impersonator impersonator;&lt;br /&gt;    &lt;span style="color:#0000ff;"&gt;private&lt;/span&gt; SPSite site;&lt;br /&gt;&lt;br /&gt;    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; TimerJobsTest()&lt;br /&gt;    {&lt;br /&gt;        impersonator = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; Impersonator();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    [TestInitialize]&lt;br /&gt;    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; Initialize()&lt;br /&gt;    {&lt;br /&gt;        &lt;span style="color:#0000ff;"&gt;using&lt;/span&gt; (SecureString securePassword = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; SecureString())&lt;br /&gt;        {&lt;br /&gt;            &lt;span style="color:#008000;"&gt;// Omitted setting secure password and &lt;/span&gt;&lt;br /&gt;            &lt;span style="color:#008000;"&gt;// retrieval of other variables for brevity.&lt;/span&gt;&lt;br /&gt;            securePassword.MakeReadOnly();&lt;br /&gt;            impersonator.ImpersonateUser(&lt;br /&gt;                adminUserName,&lt;br /&gt;                adminDomain,&lt;br /&gt;                securePassword);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        site = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; SPSite(siteUrl);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    [TestMethod]&lt;br /&gt;    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; TestJob()&lt;br /&gt;    {&lt;br /&gt;        &lt;span style="color:#0000ff;"&gt;foreach&lt;/span&gt; (SPJobDefinition job &lt;span style="color:#0000ff;"&gt;in&lt;/span&gt; site.WebApplication.JobDefinitions)&lt;br /&gt;        {&lt;br /&gt;            &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (job.Title.Equals(&lt;br /&gt;                    &lt;span style="color:#006080;"&gt;"My Job Title"&lt;/span&gt;,&lt;br /&gt;                    StringComparison.OrdinalIgnoreCase))&lt;br /&gt;            {&lt;br /&gt;                job.Execute(site.ContentDatabase.Id);&lt;br /&gt;                &lt;span style="color:#0000ff;"&gt;break&lt;/span&gt;;&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    [TestCleanup]&lt;br /&gt;    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; CleanUp()&lt;br /&gt;    {&lt;br /&gt;        site.Dispose();&lt;br /&gt;        impersonator.StopImpersonating();&lt;br /&gt;        impersonator.Dispose();&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;div id="codeSnippetWrapper"&gt;As you see I was using an &lt;span style="font-family:Courier New;"&gt;Impersonator&lt;/span&gt; class, which allowed me to control the user identity when invoking my job. This is a custom class I wrote for this and similar situations. You can get its source code &lt;a href="http://www.neganov.com/blogspotfiles/Impersonator.zip"&gt;here&lt;/a&gt;. It is far from being a rocket science (and it shouldn’t be) as it is using the old common Win32 impersonation API. Yet one thing about it is interesting: using &lt;a href="http://msdn.microsoft.com/en-us/library/system.security.securestring.aspx"&gt;SecureString&lt;/a&gt; type, something I was referring to in &lt;a href="http://neganov.blogspot.com/2008/12/simple-icmp-heartbeat-monitor.html"&gt;my earlier post&lt;/a&gt;. If you examine the code of &lt;span style="font-family:Courier New;"&gt;Impersonator.cs&lt;/span&gt;, you could see how the managed SecureString is marshaled to the unmanaged code when the Win32 API is called. By the way if you are ever using WPF &lt;a href="http://msdn.microsoft.com/en-us/library/system.windows.controls.passwordbox.aspx"&gt;PasswordBox&lt;/a&gt; control, it is capable of passing on a &lt;span style="font-family:Courier New;"&gt;SecureString&lt;/span&gt; containing password as of .NET Framework 3.5 SP1; then my impersonator becomes really handy.&lt;br /&gt;&lt;/div&gt;True, you don’t need to be fancy when testing your own code. The &lt;span style="font-family:Courier New;"&gt;Impersonator.cs &lt;/span&gt;is meant to be a reusable secure facility for impersonation so it adds some overhead. Feel free to change it if you do not intend to use it in production environment.&lt;br /&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;p&gt;3. Once this is done, you set breakpoints, attach to the WSS Timer Service process and step through your job’s code as (I hope) you normally do.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7384653670825187633-2448280081456285365?l=neganov.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://neganov.blogspot.com/2009/04/debugging-sharepoint-timer-jobs.html</link><author>noreply@blogger.com (Ivan Neganov)</author><thr:total>1</thr:total></item></channel></rss>

