<?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:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" version="2.0">

<channel>
	<title>Andy Burns' SharePoint Blog</title>
	
	<link>http://www.novolocus.com</link>
	<description>Whatever I'm working on, really...</description>
	<lastBuildDate>Wed, 21 Jul 2010 10:59:50 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/novolocus" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="novolocus" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><feedburner:emailServiceId xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">novolocus</feedburner:emailServiceId><feedburner:feedburnerHostname xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">http://feedburner.google.com</feedburner:feedburnerHostname><item>
		<title>Get the URL of a list</title>
		<link>http://www.novolocus.com/2010/07/21/get-the-url-of-a-list/</link>
		<comments>http://www.novolocus.com/2010/07/21/get-the-url-of-a-list/#comments</comments>
		<pubDate>Wed, 21 Jul 2010 10:59:50 +0000</pubDate>
		<dc:creator>Andy</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Alternate Access Mappings]]></category>
		<category><![CDATA[Navigation]]></category>
		<category><![CDATA[SPList]]></category>

		<guid isPermaLink="false">http://www.novolocus.com/?p=1870</guid>
		<description><![CDATA[This is a seemingly simple task &#8211; given a List or Library in SharePoint, how do I get it&#8217;s URL? The difficulty here is that a List has multiple URLs &#8211; one for each View on the list. We can get those URLs, but sometimes you really just want the URL to the list, without [...]]]></description>
			<content:encoded><![CDATA[<p>This is a seemingly simple task &#8211; given a List or Library in SharePoint, how do I get it&#8217;s URL? The difficulty here is that a List has multiple URLs &#8211; one for each View on the list. We can get those URLs, but sometimes you really just want the URL to the list, without the <em>/forms/something.aspx</em> bit too.</p>
<p>For example, you might want <em>http://server/siteCollection/site/lists/somelist</em> . If you entered this URL, you&#8217;d be taken to the default View for the list, so you don&#8217;t really need the extra <em>/forms/&#8230;</em> bit to identify the list &#8211; that&#8217;s all about identifying the view.</p>
<p>Sadly, though, there is no SPList.Url property or equivalent on the <a href="http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.splist_members(v=office.12).aspx"><strong>SPList</strong> </a>object. So, how can I get a list&#8217;s URL? <span id="more-1870"></span>Well, all Lists have a <strong><a href="http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.splist.rootfolder(v=office.12).aspx">RootFolder</a></strong>. This folder has a URL, relative to the <strong>SPWeb</strong> it&#8217;s in.</p>
<p> So, we can do something like this:</p>
<pre class="brush: csharp;">string url = web.Url + &quot;/&quot; + list.RootFolder.Url</pre>
<p>Well, that&#8217;s great &#8211; but the result has the full path, including the server name. This can differ in SharePoint with alternate access mappings, so it can be useful to get the server relative url instead. This can be slightly more complicated:</p>
<pre class="brush: csharp;">string url = &quot;http://server/subsite/Documents/&quot;;

using (SPSite site = new SPSite(url))
{
    using (SPWeb web = site.OpenWeb())
    {
        SPList list = web.GetList(url);

        string listurl = web.ServerRelativeUrl;
        if(listurl == &quot;/&quot;) listurl = string.Empty;
        listurl = listurl + &quot;/&quot; + list.RootFolder.Url;
        Console.WriteLine(listurl);
    }
}</pre>
<p>This should give use the <em>server relative </em>URL for the list. Note also the bit where we clear our variable if we are in the root site of the root site collection of a web application (e.g.<em> http://server/</em> ) as this returns an<strong> SPWeb.ServerRelativeUrl</strong> of <em>&#8220;/&#8221;</em></p>
]]></content:encoded>
			<wfw:commentRss>http://www.novolocus.com/2010/07/21/get-the-url-of-a-list/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Events on Adding/Deleting Fields from Content types</title>
		<link>http://www.novolocus.com/2010/06/25/events-on-addingdeleting-fields-from-content-types/</link>
		<comments>http://www.novolocus.com/2010/06/25/events-on-addingdeleting-fields-from-content-types/#comments</comments>
		<pubDate>Fri, 25 Jun 2010 09:06:56 +0000</pubDate>
		<dc:creator>Andy</dc:creator>
				<category><![CDATA[Development 2010]]></category>
		<category><![CDATA[SPField]]></category>

		<guid isPermaLink="false">http://www.novolocus.com/?p=1863</guid>
		<description><![CDATA[One of the things that&#8217;s driven me nuts in SharePoint 2007 is that there are no events to capture when a Field is added to a Content Type. There is an OnAdded event &#8211; which sometimes gets used to save Custom Properties of the field (though I prefer Gunnar Peipman&#8217;s approach)
Well, no more! In SharePoint [...]]]></description>
			<content:encoded><![CDATA[<p>One of the things that&#8217;s driven me nuts in SharePoint 2007 is that there are no events to capture when a Field is added to a Content Type. There is an OnAdded event &#8211; which sometimes gets used to save Custom Properties of the field (though <a href="http://www.novolocus.com/2010/04/29/inconvenient-getcustomproperty-and-setcustomproperty/">I prefer Gunnar Peipman&#8217;s approach</a>)</p>
<p>Well, no more! In SharePoint 2010, there are now <strong><a href="http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.spfield.onaddingtocontenttype.aspx">OnAddingToContentType()</a></strong> and <strong><a href="http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.spfield.ondeletingfromcontenttype.aspx">OnDeletingFromContentType()</a></strong>  methods. We can override this in our custom fields, and this lets us do lots of useful things &#8211; like register event handlers, add workflows, or set properties on the content type, which are things that I&#8217;ve wanted to do a few times now. So, good news!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.novolocus.com/2010/06/25/events-on-addingdeleting-fields-from-content-types/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Rendering List Fields from other sites</title>
		<link>http://www.novolocus.com/2010/06/23/rendering-list-fields-from-other-sites/</link>
		<comments>http://www.novolocus.com/2010/06/23/rendering-list-fields-from-other-sites/#comments</comments>
		<pubDate>Wed, 23 Jun 2010 09:01:14 +0000</pubDate>
		<dc:creator>Andy</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[SPContext]]></category>
		<category><![CDATA[SPField]]></category>
		<category><![CDATA[SPListItem]]></category>
		<category><![CDATA[Web Parts]]></category>

		<guid isPermaLink="false">http://www.novolocus.com/?p=1859</guid>
		<description><![CDATA[I had a requirement recently to display the fields of a SharePoint item in another SharePoint site. Now, you can do this with things like the Content Query Web Part, or Data View Web Part, but I was doing a few other things, and specifically, I needed to pull the  fields to display from a [...]]]></description>
			<content:encoded><![CDATA[<p>I had a requirement recently to display the fields of a SharePoint item in another SharePoint site. Now, you can do this with things like the Content Query Web Part, or Data View Web Part, but I was doing a few other things, and specifically, I needed to pull the  fields to display from a particular View on the list.</p>
<p>This turned out to be quite an interesting problem. All fields use a subclass of BaseFieldControl, and this is what renders the field &#8211; so it appeared to be fairly straight forward. As always, though, there was a little kink to it &#8211; you need an <strong>SPContext</strong> for the site the item comes from, and you need to use this as the contexts for the <strong>SPField</strong>&#8217;s rendering control:</p>
<pre class="brush: csharp;">SPContext ctx = SPContext.GetContext(HttpContext.Current, item.ID, relatedList.ID, relatedWeb);

SPView relatedView = list.DefaultView;

foreach (string vf in relatedView.ViewFields)
{
    SPField fld = relatedList.Fields.GetFieldByInternalName(vf);

    HtmlGenericControl titleLabel = new HtmlGenericControl(&quot;H3&quot;);
    titleLabel.InnerText = fld.Title;
    this.Controls.Add( titleLabel );

    BaseFieldControl ctl = fld.FieldRenderingControl;
    ctl.ControlMode = SPControlMode.Display;
    ctl.ListId = relatedList.ID;
    ctl.ItemId = item.ID;
    ctl.RenderContext = ctx;
    ctl.ItemContext = ctx;
    ctl.FieldName = fld.Title;
    ctl.ID = Guid.NewGuid().ToString();
   
    this.Controls.Add( ctl );
}</pre>
<p>Groovy!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.novolocus.com/2010/06/23/rendering-list-fields-from-other-sites/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Silverlight in SharePoint ‘Hello World’ demo</title>
		<link>http://www.novolocus.com/2010/06/01/silverlight-in-sharepoint-hello-world-demo/</link>
		<comments>http://www.novolocus.com/2010/06/01/silverlight-in-sharepoint-hello-world-demo/#comments</comments>
		<pubDate>Tue, 01 Jun 2010 12:20:43 +0000</pubDate>
		<dc:creator>Andy</dc:creator>
				<category><![CDATA[Development 2010]]></category>
		<category><![CDATA[SharePoint 2010]]></category>
		<category><![CDATA[Silverlight]]></category>
		<category><![CDATA[Animation]]></category>
		<category><![CDATA[SP2010]]></category>

		<guid isPermaLink="false">http://www.novolocus.com/?p=1848</guid>
		<description><![CDATA[I&#8217;ve not used Silverlight, and I though it might be interesting to try the Silverlight Web Part from SharePoint 2010, so I came up with a little &#8216;hello world&#8217; project. Using Silverlight, I wanted to:

Query a SharePoint List for data
Display that data

Not exactly complicated stuff, but I figured it would be a start. I decided [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve not used Silverlight, and I though it might be interesting to try the Silverlight Web Part from SharePoint 2010, so I came up with a little &#8216;hello world&#8217; project. Using Silverlight, I wanted to:</p>
<ul>
<li>Query a SharePoint List for data</li>
<li>Display that data</li>
</ul>
<p>Not exactly complicated stuff, but I figured it would be a start. I decided to query a Picture Library, and display the pictures in my web part, changing the displayed image every few seconds. All of this is very achievable with JavaScript or jQuery and the Content Query Web Part (as some sort of variant on the <a href="http://www.novolocus.com/software/content-query-ticker-web-part/">CQTWP </a>I built), so I thought this would be a good comparison.<span id="more-1848"></span></p>
<p>I created a Silverlight Application Project in Visual Studio, and didn&#8217;t create a web site to host it (we&#8217;re going to use SharePoint)</p>
<p>I added references to <strong>Microsoft.SharePoint.Client.Silverlight</strong> and <strong>Microsoft.SharePoint.Client.Silverlight.Runtime</strong> assemblies in the <em>14/TEMPLATES/LAYOUTS/ClientBin</em> directory.</p>
<p>In my MainPage XAML, I added an image control:</p>
<pre class="brush: xml;">&lt;Grid x:Name=&quot;LayoutRoot&quot; Background=&quot;White&quot; Loaded=&quot;LayoutRoot_Loaded&quot;&gt;
        &lt;Image Height=&quot;300&quot; HorizontalAlignment=&quot;Left&quot; Name=&quot;theImage&quot; Stretch=&quot;Fill&quot; VerticalAlignment=&quot;Top&quot; Width=&quot;400&quot; /&gt;
&lt;/Grid&gt;</pre>
<p>Fine &#8211; but how do we get the images into it, to display? Well, I started by creating a function to run when the Layout Root was loaded. In it we:</p>
<ul>
<li>Get the context of the site (SPWeb)</li>
<li>Get the &#8216;Pics&#8217; list (yes, hard coded for this demo)</li>
<li>Construct a CAML query for the images</li>
<li>Execute the query asynchronously</li>
</ul>
<pre class="brush: csharp;">public partial class MainPage : UserControl
    {

        //class variables
        SP.ClientContext context;
        SP.Web myWeb;
        SP.List myList;
        SP.ListItemCollection myItems;
        List&lt;string&gt; files = new List&lt;string&gt;();
        System.Windows.Threading.DispatcherTimer myDispatcherTimer;

        private int _currentIndex = 0;

        private void LayoutRoot_Loaded(object sender, RoutedEventArgs e)
        {
            context = SP.ClientContext.Current;
            myWeb = context.Web;
            //Get handle to document library
            myList = myWeb.Lists.GetByTitle(&quot;MyPics&quot;);

            SP.CamlQuery query = new SP.CamlQuery();
            query.ViewXml = &quot;&lt;View&gt;&lt;/View&gt;&quot;;
            myItems = myList.GetItems(query);

            context.Load(myList);
            context.Load(myItems);

            context.ExecuteQueryAsync(getRequestSucceeded, getRequestFailed);
        }</pre>
<p>So, next, what to do on Success or Failure? Well, let&#8217;s do failure first &#8211; show an error message</p>
<pre class="brush: csharp;">private void getRequestFailed(object sender, SP.ClientRequestFailedEventArgs e)
        {
            Dispatcher.BeginInvoke(() =&gt; { MessageBox.Show(&quot;Error occured:  &quot; + e.Message); });
        }</pre>
<p>Fine. And on Success? Well, we want to:</p>
<ul>
<li>Add our results to a list of image files to show,</li>
<li>Start a timer that changes the image being shown every few seconds</li>
</ul>
<pre class="brush: csharp;">

 private void getRequestSucceeded(object sender, SP.ClientRequestSucceededEventArgs e)
{
    Dispatcher.BeginInvoke(() =&gt;
    {
 //iterate through each file and add file to our list of files       
 foreach (SP.ListItem item in myItems)
 {
     files.Add(item[&quot;FileRef&quot;].ToString());
 }

 // Do something with our data!
 myDispatcherTimer = new System.Windows.Threading.DispatcherTimer();
 myDispatcherTimer.Interval = new TimeSpan(0, 0, 0, 0, 2000);
 myDispatcherTimer.Tick += new EventHandler(Each_Tick);
 myDispatcherTimer.Start();

    });
}</pre>
<p>That&#8217;s fine &#8211; but what happens every few seconds (in the<strong> Each_Tick</strong> delegate?) Well, I wanted a nice &#8216;Fade Out, fade in&#8217;, but this proved tricky. In the end <a href="http://dotnetgui.blogspot.com/2008/12/how-to-make-image-slide-show.html">I referred to this example</a>, which showed me how to define my animations in the XAML:</p>
<pre class="brush: xml;">&lt;UserControl.Resources&gt;
        &lt;Storyboard x:Name=&quot;FadeOutAnimation&quot; Completed=&quot;FadeOutAnimation_Completed&quot;&gt;
            &lt;DoubleAnimation Duration=&quot;00:00:00.50&quot; From=&quot;1&quot; To=&quot;0&quot; Storyboard.TargetProperty=&quot;Opacity&quot; Storyboard.TargetName=&quot;theImage&quot; /&gt;
        &lt;/Storyboard&gt;
        &lt;Storyboard x:Name=&quot;FadeInAnimation&quot;&gt;
            &lt;DoubleAnimation Duration=&quot;00:00:00.50&quot; From=&quot;0&quot; To=&quot;1&quot; Storyboard.TargetProperty=&quot;Opacity&quot; Storyboard.TargetName=&quot;theImage&quot; /&gt;
        &lt;/Storyboard&gt;
&lt;/UserControl.Resources&gt;</pre>
<p>Fine, so I&#8217;ve got animations defined &#8211; how do I use them? Well, in my Each_Tick delegate, I incremented the index of the image to be shown, and started the <em>Fade Out</em> animation. Then, when the Fade Out animation completes, it changes the image to be displayed, and starts the Fade In animation:</p>
<pre class="brush: csharp;"> public void Each_Tick(object o, EventArgs sender)
{
    _currentIndex++;    
    if (_currentIndex == files.Count){
       _currentIndex = 0;    
    }    
    FadeOutAnimation.Begin();
}

private void FadeOutAnimation_Completed(object sender, EventArgs e)
{
    BitmapImage bmi = new BitmapImage(new Uri(files[_currentIndex], UriKind.Relative));
    theImage.Source = bmi;
    FadeInAnimation.Begin();
}
</pre>
<p>And that&#8217;s it! Sadly, I can&#8217;t easily display it &#8211; a static image doesn&#8217;t do it justice &#8211; but that&#8217;s all there is to it.</p>
<p>So, my conclusions? Well, I though that querying the list might be tricky &#8211; but it was pretty straight forward, to be honest. The hardest part of this was the fading in and out animation, which I suspect is simply down to my lack of experience with SilverLight. I think that if I really knew what I was doing with Silverlight in the same way as I do with jQuery or JavaScript, Silverlight would actually be easier to have created this effect in.</p>
<p>I guess the next question would be feeding in Properties that a user can edit &#8211; such as the picture library name &#8211; so that the web part is easily reusable.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.novolocus.com/2010/06/01/silverlight-in-sharepoint-hello-world-demo/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Getting Absolute URLs in SharePoint</title>
		<link>http://www.novolocus.com/2010/05/25/getting-absolute-urls-in-sharepoint/</link>
		<comments>http://www.novolocus.com/2010/05/25/getting-absolute-urls-in-sharepoint/#comments</comments>
		<pubDate>Tue, 25 May 2010 10:55:21 +0000</pubDate>
		<dc:creator>Andy</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Alternate Access Mappings]]></category>
		<category><![CDATA[SPSite]]></category>

		<guid isPermaLink="false">http://www.novolocus.com/?p=1845</guid>
		<description><![CDATA[This is a bit of a reminder for myself, but quite a lot of the URLs you deal with in SharePoint development are relative &#8211; that is, something like an SPList.DefaultViewURL might be:
/sites/web/lists/list/allitems.aspx
That&#8217;s fine &#8230; but sometimes you need a full absolute URL. For example, you might be sending out an email with a hyperlink [...]]]></description>
			<content:encoded><![CDATA[<p>This is a bit of a reminder for myself, but quite a lot of the URLs you deal with in SharePoint development are relative &#8211; that is, something like an <strong>SPList.DefaultViewURL</strong> might be:</p>
<p><code>/sites/web/lists/list/allitems.aspx</code></p>
<p>That&#8217;s fine &#8230; but sometimes you need a full absolute URL. For example, you might be sending out an email with a hyperlink in it &#8211; a relative URL ain&#8217;t going to cut it.</p>
<p>Fortunately, there is a very useful function &#8211; <a href="http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.spsite.makefullurl.aspx"><strong>SPSite.MakeFullUrl()</strong> </a>:</p>
<blockquote><p>Returns the full URL for the specified server-relative URL.</p></blockquote>
<p>That&#8217;s great &#8211; but it raises some questions. What about Alternate Access Maps? What URL would be returned? Well, predictably, the URL used in the <a href="http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.spsite.spsite(v=office.14).aspx"><strong>SPSite</strong> Constructor</a> in the first place. Mostly, they either accept a URL (which defines a zone), or they accept a GUID and an <a href="http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.administration.spurlzone(v=office.14).aspx"><strong>SPUrlZone</strong> </a>value. There is a constructor that just accepts a GUID &#8211; which will then use the default zone. Similarly, the constructor accepting a GUID and <strong>SPUserToken</strong> also uses the Default Zone.</p>
<p><em>(If you open it up in reflector, you can see it just calling a private constructor passing the <strong>SPUrlZone.Default</strong> value).</em></p>
]]></content:encoded>
			<wfw:commentRss>http://www.novolocus.com/2010/05/25/getting-absolute-urls-in-sharepoint/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>“To save to the server, correct the invalid or missing required properties”</title>
		<link>http://www.novolocus.com/2010/05/10/to-save-to-the-server-correct-the-invalid-or-missing-required-properties/</link>
		<comments>http://www.novolocus.com/2010/05/10/to-save-to-the-server-correct-the-invalid-or-missing-required-properties/#comments</comments>
		<pubDate>Mon, 10 May 2010 08:32:44 +0000</pubDate>
		<dc:creator>Andy</dc:creator>
				<category><![CDATA[Admin]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Content Approval]]></category>
		<category><![CDATA[Document Templates]]></category>
		<category><![CDATA[SPField]]></category>
		<category><![CDATA[Versions]]></category>

		<guid isPermaLink="false">http://www.novolocus.com/?p=1843</guid>
		<description><![CDATA[I&#8217;ve been working on a custom field for, well, a while now, and after making some changes I started to get the error &#8220;To save to the server, correct the invalid or missing required properties&#8221; when trying to edit a document and save the changes back in Word 2007. This was a little strange, as [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been working on a custom field for, well, a while now, and after making some changes I started to get the error &#8220;To save to the server, correct the invalid or missing required properties&#8221; when trying to edit a document and save the changes back in Word 2007. This was a little strange, as I&#8217;d already sorted out <a href="http://www.novolocus.com/2010/04/13/hide-a-custom-field-from-the-dip/">hiding the custom field from the document information panel</a>, and things had been working fine since then.</p>
<p>New documents seemed to be alright, but the older ones weren&#8217;t. So, maybe the problems were all the old documents, rather than my field.</p>
<p>Eventually, I came across <a href="http://support.microsoft.com/kb/928037">this knowledgebase article</a> &#8211; so I &#8220;inspected&#8221; the document, removed any of it&#8217;s custom data, and resaved it &#8211; and it worked fine.</p>
<p>What I think happened here was, I was testing different settings for Content Approval and Versioning on my document libraries. I think the troublesome documents were created when one of those was set to be &#8216;on&#8217;, and I subsequently turned it &#8216;off&#8217;. This meant that the document actually had extra data that referred to a column that no longer existed (I think) &#8211; which probably means this is related to Content Approval.</p>
<p>But I&#8217;d be curious if anyone else has managed to cause this error, and how they did so.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.novolocus.com/2010/05/10/to-save-to-the-server-correct-the-invalid-or-missing-required-properties/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Inconvenient GetCustomProperty and SetCustomProperty</title>
		<link>http://www.novolocus.com/2010/04/29/inconvenient-getcustomproperty-and-setcustomproperty/</link>
		<comments>http://www.novolocus.com/2010/04/29/inconvenient-getcustomproperty-and-setcustomproperty/#comments</comments>
		<pubDate>Thu, 29 Apr 2010 08:45:18 +0000</pubDate>
		<dc:creator>Andy</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[SPField]]></category>

		<guid isPermaLink="false">http://www.novolocus.com/?p=1839</guid>
		<description><![CDATA[So, I&#8217;m working on a custom field definition for SharePoint. My field has a few custom properties that you need to fill in when you create it. However, after creation, those fields were empty &#8211; they were simply never set. You could then update them, and that worked fine, but creation was broken.
The code I&#8217;d [...]]]></description>
			<content:encoded><![CDATA[<p>So, I&#8217;m working on a custom field definition for SharePoint. My field has a few custom properties that you need to fill in when you create it. However, after creation, those fields were empty &#8211; they were simply never set. You could then update them, and that worked fine, but creation was broken.</p>
<p>The code I&#8217;d inherited was trying to solve this problem (it&#8217;s a known issue) <a href="http://social.msdn.microsoft.com/Forums/en-US/sharepointdevelopment/thread/fb1cb936-3abb-48c2-8d19-49007688dc34/">this way </a>- which is a bit ugly. It also holds memory for the Dictionary of values that, as far as I could see, was only being freed on IISReset. Yuck. And it didn&#8217;t work in our code, despite matching the example in that thread quite closely.</p>
<p>Fortunately, I came across a neat post on Gunnar Peipman&#8217;s blog &#8211; <a href="http://weblogs.asp.net/gunnarpeipman/archive/2009/02/03/sharepoint-temporary-solution-for-getcustomproperty-and-setcustomproperty-errors.aspx">Temporary Solution for GetCustomProperty an SetCustomProperty Errors</a>. I don&#8217;t like using reflection to invoke the methods I need to use, but at least it&#8217;s <em>a</em> solution, even if not ideal. And it works!</p>
<p>Please go to Gunnar&#8217;s post &#8211; but just in case his blog goes down, I&#8217;m going to shamelessly plagiarise his code below&#8230;</p>
<p>Thanks Gunnar!<span id="more-1839"></span></p>
<p>Uses the System.Reflection API.</p>
<pre class="brush: csharp;">
        private void SetFieldAttribute(string attribute, string value)
        {
            Type baseType;
            BindingFlags flags;
            MethodInfo mi;

            baseType = typeof(SemaphoreField);
            flags = BindingFlags.Instance | BindingFlags.NonPublic;
            mi = baseType.GetMethod(&quot;SetFieldAttributeValue&quot;, flags);
            mi.Invoke(this, new object[] { attribute, value });
        }

        private string GetFieldAttribute(string attribute)
        {
            Type baseType;
            BindingFlags flags;
            MethodInfo mi;

            baseType = typeof(SemaphoreField);
            flags = BindingFlags.Instance | BindingFlags.NonPublic;
            mi = baseType.GetMethod(&quot;GetFieldAttributeValue&quot;,
                                        flags,
                                        null,
                                        new Type[] { typeof(String) },
                                        null);

            object obj = mi.Invoke(this, new object[] { attribute });

            if (obj == null)
                return &quot;&quot;;
            else
                return obj.ToString();
        }
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.novolocus.com/2010/04/29/inconvenient-getcustomproperty-and-setcustomproperty/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Registering EventHandlers against ContentTypes</title>
		<link>http://www.novolocus.com/2010/04/28/registering-eventhandlers-against-contenttypes/</link>
		<comments>http://www.novolocus.com/2010/04/28/registering-eventhandlers-against-contenttypes/#comments</comments>
		<pubDate>Wed, 28 Apr 2010 13:09:25 +0000</pubDate>
		<dc:creator>Andy</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Event Receivers]]></category>
		<category><![CDATA[SPContentType]]></category>
		<category><![CDATA[SPFeatureReceiver]]></category>
		<category><![CDATA[SPItemEventReceiver]]></category>

		<guid isPermaLink="false">http://www.novolocus.com/?p=1829</guid>
		<description><![CDATA[In SharePoint, Event Handlers (or Event Receivers &#8211; whichever terminology, a child of SPItemEventReceiver) can be registered against lists/libraries. You can do this through an SPWeb (site) scoped feature, declaratively or programmatically with an SPEventReceiverDefinition.
Unfortunately, you can&#8217;t declaratively register event receivers at the SPSite (Site collection) level &#8211; which would be fantastic &#8211; just turn [...]]]></description>
			<content:encoded><![CDATA[<p>In SharePoint, Event Handlers (or Event Receivers &#8211; whichever terminology, a child of <strong><a href="http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.spitemeventreceiver.aspx">SPItemEventReceiver</a></strong>) can be <a href="http://msdn.microsoft.com/en-us/library/ms475328.aspx">registered </a>against lists/libraries. You can do this through an <strong>SPWeb</strong> (site) scoped feature, <a href="http://msdn.microsoft.com/en-gb/library/ms460929.aspx">declaratively</a> or <a href="http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.speventreceiverdefinition.aspx">programmatically with an <strong>SPEventReceiverDefinition</strong></a>.</p>
<p>Unfortunately, you can&#8217;t declaratively register event receivers at the <strong>SPSite</strong> (Site collection) level &#8211; which would be fantastic &#8211; just turn on the feature and across all your site collection lists/libraries of a give type would get additional event receivers. Personally, I think this may be a bug; I don&#8217;t see why this shouldn&#8217;t work at the <strong>SPSite</strong> level.</p>
<p>Anyway, there is still another option &#8211; we could register our event against a particular Content Type. This is a less often used approach, which raises two questions &#8211; how do you do it, and what happens to child Content Types?<span id="more-1829"></span></p>
<p>So, how do you register the event? Well, first off, you can&#8217;t do it declaratively &#8211; CAML won&#8217;t let you register against a Content Type. That seems a bit of an omission. Still, we still have the programmatic option through SharePoint&#8217;s API &#8211; something like:</p>
<pre class="brush: csharp;">private void RegisterEventHandler(SPContentType ct, string name,
             int sequence, string evAssembly, string evClass, SPEventReceiverType type)
{
    SPEventReceiverDefinition oEv = ct.EventReceivers.Add();
    oEv.Name = name;
    oEv.Type = type;
    oEv.SequenceNumber = sequence;
    oEv.Assembly = evAssembly;
    oEv.Class = evClass;
    oEv.Data = string.Empty;
    oEv.Update();
}</pre>
<p>Great! But what runs this? Well, we&#8217;ll want to use a Feature, and we can&#8217;t add it declaratively &#8211; so I&#8217;ll use a Feature Receiver (<strong><a href="http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.spfeaturereceiver.aspx">SPFeatureReceiver</a></strong>). When the feature is activated/deactivated, it&#8217;ll run some code, and we&#8217;ll add/remove our event receiver. The code I come up with was</p>
<pre class="brush: csharp;">

using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.SharePoint;

namespace EventReceiverTest
{
    class AWBRegisterEventHandler : SPFeatureReceiver
    {
        private string[] cts = new string[] { &quot;0x0101&quot; };

        public override void FeatureActivated(SPFeatureReceiverProperties properties)
        {

            foreach (string ct in cts)
            {
                try
                {
                    SPContentTypeId ctId = new SPContentTypeId(ct);
                    SPSite site = properties.Feature.Parent as SPSite;

                    if (site == null)
                    {
                        throw new ArgumentException(&quot;Feature must be activated at an SPSite level&quot;);
                    }

                    SPContentType currentCT = site.RootWeb.ContentTypes[ctId];

                    if (currentCT == null)
                    {
                        throw new ArgumentException(string.Format(&quot;Content Type ID {0} not found&quot;));
                    }

      string evClass = typeof(AWBEventHandler).FullName;
      string evAssembly = typeof(AWBEventHandler).Assembly.FullName;

                    RegisterEventHandler(currentCT,&quot;Content Type Event Receiver&quot;, 1000, evAssembly, evClass, SPEventReceiverType.ItemAdding);
                    RegisterEventHandler(currentCT,&quot;Content Type Event Receiver&quot;, 1000, evAssembly, evClass, SPEventReceiverType.ItemAdded);
                    RegisterEventHandler(currentCT,&quot;Content Type Event Receiver&quot;, 1000, evAssembly, evClass, SPEventReceiverType.ItemUpdating);
                    RegisterEventHandler(currentCT,&quot;Content Type Event Receiver&quot;, 1000, evAssembly, evClass, SPEventReceiverType.ItemUpdated);

                    currentCT.Update(true, false);

                }
                catch (Exception ex)
                {
                    throw new SPException(&quot;Failed to add event receiver to content type&quot;, ex);
                }

            }

        }

        public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
        {

            foreach (string ct in cts)
            {
                try
                {
                    SPContentTypeId ctId = new SPContentTypeId(ct);
                    SPSite site = properties.Feature.Parent as SPSite;

                    if (site == null)
                    {
                        throw new ArgumentException(&quot;Feature must be activated at an SPSite level&quot;);
                    }

                    SPContentType currentCT = site.RootWeb.ContentTypes[ctId];

                    if (currentCT == null)
                    {
                        throw new ArgumentException(string.Format(&quot;Content Type ID {0} not found&quot;));
                    }
      string evClass = typeof(AWBEventHandler).FullName;
                    UnregisterAllEventHandlers(currentCT, evClass);

                }
                catch (Exception ex)
                {
                    throw new SPException(&quot;Failed to remove event receiver from content type&quot;, ex);
                }
            }
        }
        public override void FeatureInstalled(SPFeatureReceiverProperties properties)
        {
        }

        public override void FeatureUninstalling(SPFeatureReceiverProperties properties)
        {
        }
 
        private void RegisterEventHandler(SPContentType ct, string name, int sequence,
            string evAssembly, string evClass, SPEventReceiverType type)
        {
            SPEventReceiverDefinition oEv = ct.EventReceivers.Add();
            oEv.Name = name;
            oEv.Type = type;
            oEv.Assembly = evAssembly;
            oEv.Class = evClass;
            oEv.SequenceNumber = sequence;
            oEv.Data = string.Empty;
            oEv.Update();
        }

        private void UnregisterAllEventHandlers(SPContentType ct, string evClass)
        {
            bool bContinueDelete = true;
            while (bContinueDelete)
            {
                if (ct.EventReceivers.Count &lt; 1)
                {
                    bContinueDelete = false;
                }
                else
                {
                    bool bFoundOne = false;
                    foreach (SPEventReceiverDefinition d in ct.EventReceivers)
                    {
                        if (d.Class == evClass)
                        {
                            d.Delete();
                            ct.Update(true,false);
                            bFoundOne = true;
                            break;
                        }
                    }
                    if (!bFoundOne)
                    {
                        bContinueDelete = false;
                    }
                }

            }
        }
    }
}</pre>
<p>This code will register/unregister my <em>AWBEventHandler</em> class, for Content Types based on Documents (oxo1o1). By adding more elements into the array at the top, we could register against more content types. Naturally, a more sensible thing would be to have a Feature <a href="http://msdn.microsoft.com/en-gb/library/ms475601.aspx">Property </a>elements feeding in things like the <em>Assembly</em>, <em>Class</em>, Event <em>Name</em>, and <em>Content Types</em>, but this is just an example.</p>
<p>Note that the UnregisterAllEventHandlers is a little strange. Normally, I&#8217;d write something like:</p>
<pre class="brush: csharp;">private void UnregisterAllEventHandlers(SPContentType ct, string evClass)
{
    List&lt;SPEventReceiverDefinition&gt; toRemove = new List&lt;SPEventReceiverDefinition&gt;();
    foreach (SPEventReceiverDefinition d in ct.EventReceivers)
    {
        if (d.Class == evClass)
        {
            toRemove.Add(d);
        }
    }
    foreach (SPEventReceiverDefinition d2 in toRemove)
    {
        d2.Delete();
    }
}</pre>
<p>In that function, we iterate over the <a href="http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.speventreceiverdefinitioncollection.aspx"><strong>SPEventReceiverDefinitionCollection</strong> </a>generating a list of things to delete, and then delete them. We don&#8217;t delete them in the first for loop as deleting an item invalidate the enumerator for the for loop &#8211; so it throws an exception. Anyway, I tried using that function, and it didn&#8217;t remove all of the event receivers. I don&#8217;t know why &#8211; it works fine on lists. Instead, I developed the weird looking function shown above.</p>
<p>All of which is fine, but this still leaves a question &#8211; will these events be registered for child content types? In our code, we&#8217;ve got the line:</p>
<pre class="brush: csharp;">currentCT.Update(true, false);</pre>
<p>That <strong><a href="http://msdn.microsoft.com/en-us/library/ms475130(v=office.12).aspx">.Update(true,false)</a></strong> call will update child content types, and not throw an exception if it tries to update a sealed content type (important if you&#8217;re trying to register against something as general as the &#8216;Document&#8217; content type. So the short answer is <strong>yes</strong>, our event receiver will be registered against child content types.</p>
<p>For example, I had a document library which allowed two document content types:</p>
<p><a href="http://www.novolocus.com/wp-content/uploads/2010/04/Multiple-Content-Type-Library.png"><img class="alignnone size-medium wp-image-1836" title="Multiple Content Type Library" src="http://www.novolocus.com/wp-content/uploads/2010/04/Multiple-Content-Type-Library-300x175.png" alt="" width="300" height="175" /></a></p>
<p>After registering against the Site content type for Documents, I used SharePoint Manager to see what event receivers I had registered in my Site collection. The image below shows a Library which has only one content type at the top, and one with 2 content types below. You can see that there are 4 event receivers registered per content type.</p>
<p><a href="http://www.novolocus.com/wp-content/uploads/2010/04/SPM-after-registering-and-updating-children.png"><img class="alignnone size-medium wp-image-1835" title="SPM after registering and updating children" src="http://www.novolocus.com/wp-content/uploads/2010/04/SPM-after-registering-and-updating-children-249x300.png" alt="" width="249" height="300" /></a></p>
<p><em>Note &#8211; if you change the Content Type after uploading a document &#8211; which you can through the user interface &#8211; and save that change then the <span style="text-decoration: underline;">other</span> content type&#8217;s event receiver is run for ItemUpdated.</em></p>
<p>What might be interesting is the question &#8211; if we got our <strong>SPContentType</strong> object from an <strong>SPWeb</strong> (as above) &#8211; therefore as a<a href="http://www.novolocus.com/2008/03/28/content-types-whos-your-daddy/"> Site Content Type</a>, and didn&#8217;t apply the event receiver to child content types, would the list content types get the event receivers? Short answer &#8211; existing children would not, but I&#8217;m pretty sure that new child content types would.</p>
<p>So, in summary &#8211; above we&#8217;ve seen how to register and unregister an event receiver against a content type and all it&#8217;s child content types. And that seems to work pretty well! This has the advantage that it&#8217;s pretty simple, therefore, to add an event receiver across an entire Site Collection in one feature, rather than need a feature activated for each Web.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.novolocus.com/2010/04/28/registering-eventhandlers-against-contenttypes/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Bloody Wikis in SharePoint 2007</title>
		<link>http://www.novolocus.com/2010/04/20/bloody-wikis-in-sharepoint-2007/</link>
		<comments>http://www.novolocus.com/2010/04/20/bloody-wikis-in-sharepoint-2007/#comments</comments>
		<pubDate>Tue, 20 Apr 2010 12:09:27 +0000</pubDate>
		<dc:creator>Andy</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[SPListItem]]></category>
		<category><![CDATA[Wiki]]></category>

		<guid isPermaLink="false">http://www.novolocus.com/?p=1826</guid>
		<description><![CDATA[The other day I blogged about how weird &#8216;Blog Posts&#8217; are. Well, I&#8217;ve also been looking at Wiki pages&#8230;
So, first off, as a reminder to myself, Wiki libraries are defined in the &#8216;WebPageLibrary&#8217; feature. Took a while to track that down.
Second off, calling the SPListItem.Title for a Wiki pages causes an ArgumentException. (Waldek Mastykarz has [...]]]></description>
			<content:encoded><![CDATA[<p>The other day I blogged about how weird &#8216;Blog Posts&#8217; are. Well, I&#8217;ve also been looking at Wiki pages&#8230;</p>
<p>So, first off, as a reminder to myself, Wiki libraries are defined in the <em>&#8216;WebPageLibrary&#8217;</em> feature. Took a while to track that down.</p>
<p>Second off, calling the <strong>SPListItem.Title</strong> for a Wiki pages causes an <strong>ArgumentException</strong>. (<a href="http://blog.mastykarz.nl/programmatically-creating-wiki-pages/">Waldek Mastykarz has written about this</a>). Kind of makes sense &#8211; the wiki item doesn&#8217;t have a title &#8211; but I&#8217;d prefer it returned the filename (without extension) instead. That would seem a more useful compromise.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.novolocus.com/2010/04/20/bloody-wikis-in-sharepoint-2007/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Weird ContentType of Blog Posts</title>
		<link>http://www.novolocus.com/2010/04/16/weird-contenttype-of-blog-posts/</link>
		<comments>http://www.novolocus.com/2010/04/16/weird-contenttype-of-blog-posts/#comments</comments>
		<pubDate>Fri, 16 Apr 2010 09:16:14 +0000</pubDate>
		<dc:creator>Andy</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Blogs]]></category>
		<category><![CDATA[Content Type]]></category>
		<category><![CDATA[SPContentType]]></category>
		<category><![CDATA[SPListItem]]></category>

		<guid isPermaLink="false">http://www.novolocus.com/?p=1817</guid>
		<description><![CDATA[Okay, this is weird.
I&#8217;m trying to do something with various types of item, including Blog Posts, in SharePoint. Naturally, I&#8217;m getting the SPListItem for them, and then the SPListItem.ContentType, so I can check what kind of item is it. The weird thing is, if I try to get a Blog Post, the SPListItem.ContentType is NULL.
The [...]]]></description>
			<content:encoded><![CDATA[<p>Okay, this is weird.</p>
<p>I&#8217;m trying to do something with various types of item, including Blog Posts, in SharePoint. Naturally, I&#8217;m getting the <strong>SPListItem</strong> for them, and then the <strong><a href="http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.splistitem.contenttype(v=office.12).aspx">SPListItem.ContentType</a></strong>, so I can check what kind of item is it. The weird thing is, if I try to get a Blog Post, the <strong>SPListItem.ContentType</strong> is <strong><em>NULL</em></strong>.<span id="more-1817"></span></p>
<p>The code I&#8217;m running is:</p>
<pre class="brush: csharp;">

static void Main(string[] args)
{
    string url = &quot;http://vm-moss2007/sub/blog/Lists/Posts/&quot;;
    using (SPSite site = new SPSite(url))
    {
        using (SPWeb web = site.OpenWeb())
        {
            SPList list = web.GetList(url);
            SPListItem item = list.GetItemById(1);

     Console.WriteLine(item.DisplayName);
     if (item.ContentType == null)
     {
         Console.WriteLine(&quot;ContentType is Null&quot;);
     }
     else
     {
         Console.WriteLine(item.ContentType);
     }
 }
    }
}</pre>
<p>I was running this code in a console application on the server. The URL is to a Blog Post library in a Blog site. When run, the output was:</p>
<p><a href="http://www.novolocus.com/wp-content/uploads/2010/04/BlogTesting.png"><img class="alignnone size-medium wp-image-1818" title="Blog ListItem returns NULL" src="http://www.novolocus.com/wp-content/uploads/2010/04/BlogTesting-300x168.png" alt="" width="300" height="168" /></a></p>
<p>I then tried this, but using a URL to a Pages Library. This shows an output type of <strong>SPContentType</strong> &#8211; which is what I&#8217;d expect.</p>
<p><a href="http://www.novolocus.com/wp-content/uploads/2010/04/BlogTesting-on-a-pages-library.png"><img class="alignnone size-medium wp-image-1819" title="Pages Library returns a correct Object class of SPContentType" src="http://www.novolocus.com/wp-content/uploads/2010/04/BlogTesting-on-a-pages-library-300x151.png" alt="" width="300" height="151" /></a></p>
<p>That&#8217;s weird. I mean, the item clearly DOES have a content type at some level &#8211; there is an <a href="http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.spbuiltincontenttypeid.blogpost(v=office.12).aspx"><strong>SPBuiltInContentTypeId.BlogPost</strong> </a>value. However, SharePoint Manager doesn&#8217;t show it, my code reports it  as NULL, and I can&#8217;t find any references to this anywhere! And the Advanced Settings page for a Blog&#8217;s &#8220;Posts&#8221; list doesn&#8217;t have an option &#8220;Allow Management of Content Types&#8221;.</p>
<p><a href="http://www.novolocus.com/wp-content/uploads/2010/04/Blog-Posts-List-Settings.png"><img class="alignnone size-medium wp-image-1820" title="Blog Posts List Settings" src="http://www.novolocus.com/wp-content/uploads/2010/04/Blog-Posts-List-Settings-300x219.png" alt="" width="300" height="219" /></a></p>
<p>Views can <em>show</em>  the Content Type column, which reports itself as &#8216;Post&#8217; for each item.</p>
<p><a href="http://www.novolocus.com/wp-content/uploads/2010/04/Blog-Posts-List-View.png"><img class="alignnone size-medium wp-image-1821" title="Blog Posts List View" src="http://www.novolocus.com/wp-content/uploads/2010/04/Blog-Posts-List-View-300x103.png" alt="" width="300" height="103" /></a></p>
<p>Anyone else ever seen this?</p>
]]></content:encoded>
			<wfw:commentRss>http://www.novolocus.com/2010/04/16/weird-contenttype-of-blog-posts/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Themes in SharePoint 2010</title>
		<link>http://www.novolocus.com/2010/04/14/themes-in-sharepoint-2010/</link>
		<comments>http://www.novolocus.com/2010/04/14/themes-in-sharepoint-2010/#comments</comments>
		<pubDate>Wed, 14 Apr 2010 07:42:21 +0000</pubDate>
		<dc:creator>Andy</dc:creator>
				<category><![CDATA[Branding 2010]]></category>
		<category><![CDATA[Branding]]></category>
		<category><![CDATA[PowerPoint]]></category>
		<category><![CDATA[Themes]]></category>

		<guid isPermaLink="false">http://www.novolocus.com/?p=1809</guid>
		<description><![CDATA[So, followers of this blog will know that I seem to get quite a lot of branding tasks, and that I don&#8217;t much like themes, preferring to use either the AlternateCssUrl and  Features instead. Features are great &#8211; you can deploy the CSS/image files you need, set master pages (and handle Meeting Workspaces), themes, AlternateCssUrls. They can [...]]]></description>
			<content:encoded><![CDATA[<p>So, followers of this blog will know that I seem to get quite a lot of <a href="http://www.novolocus.com/tag/branding/">branding </a>tasks, and that <a href="http://www.novolocus.com/2008/11/10/where-to-put-css-when-branding/">I don&#8217;t much like themes</a>, preferring to use either the AlternateCssUrl and  <a href="http://www.novolocus.com/2009/02/12/feature-stapling-for-branding/">Features </a>instead. Features are great &#8211; you can deploy the CSS/image files you need, set master pages (and handle <a href="http://www.novolocus.com/2008/10/30/feature-receiver-to-apply-master-pages/">Meeting Workspaces</a>), themes, AlternateCssUrls. They can also add <a href="http://www.novolocus.com/2009/12/29/application-master-page-changer-project/">HTTP Modules for branding Application Pages</a>.</p>
<p>Themes, on the other hand, are<a href="http://www.novolocus.com/2009/06/25/automatically-add-themes-to-the-spthemes-xml-file/"> fiddly to install automatically</a>, don&#8217;t work on the <a href="http://www.novolocus.com/2008/10/20/style-the-datepicker-using-an-alternate-css/">DatePicker</a>, and are individual to each site once applied. To pick up changes to a global theme, you&#8217;d have to apply a different theme and then reapply the desired theme -<em> for every site</em>.</p>
<p>Well, that was with SharePoint 2007. SharePoint 2010 is a bit different, as I got to find out on a Combined Knowledge course in January (and this is the first time I&#8217;ve managed to write about it!)<span id="more-1809"></span></p>
<p>Themes in SharePoint 2010 are, well, really quite neat. The branding itself is made up of images and CSS &#8211; no surprise there. However, you can &#8216;annotate&#8217; your CSS so that particular colours can be replaced by your theme. The colour schemes themeselves are defined in PowerPoint. Yes, <em>PowerPoint</em>. I was suspicious, but works pretty well. (You can also use SharePoint Designer too &#8211; see below). There are the built in ones:</p>
<p><a href="http://www.novolocus.com/wp-content/uploads/2010/04/Themes1.png"><img class="alignnone size-medium wp-image-1811" title="Themes Dialog in PowerPoint" src="http://www.novolocus.com/wp-content/uploads/2010/04/Themes1-132x300.png" alt="" width="132" height="300" /></a></p>
<p>But more likely, you&#8217;ll be defining your own 12 colours:</p>
<p><a href="http://www.novolocus.com/wp-content/uploads/2010/04/Themes2.png"><img class="alignnone size-medium wp-image-1812" title="Create a Theme in PowerPoint" src="http://www.novolocus.com/wp-content/uploads/2010/04/Themes2-290x300.png" alt="" width="290" height="300" /></a></p>
<p>You can save this theme as a &#8216;.thmx&#8217; which you can then upload to SharePoint, and use! No changing XML files or anything!</p>
<p>However, the problem in 2007 of doing just a global replace of CSS colours was that a lot of the branding for SharePoint is done through images &#8211; all of the menus, the little gradients on toolbars, the background of the pages &#8211; there are a lot of images, and regenerating these took time. Well, in SharePoint 2010 your can annotate images used in your CSS to be regenerated using the colours of your theme. That&#8217;s right, instead of having to manually create those images, you can get SharePoint to do it for you. It&#8217;ll even do just areas of the image. For example, if your site had a single which showed one of those stock pictures of &#8216;happy people looking at a PC&#8217; and a company logo, you might want to re-color the people, but not the logo bit. SharePoint 2010 can do that. Wow! I think this will allow the sort of &#8216;basic&#8217; branding that a lot of organisations want internally.</p>
<p><strong>Edit</strong>: actually, the <a href="http://blogs.msdn.com/sharepointdesigner/archive/2010/04/09/working-with-the-sharepoint-theming-engine.aspx">SharePoint Designer blog has a good example</a>. I can&#8217;t say that I blame them for being stoked &#8211; this is really neat! Well, provided the core styles have been designed properly, with themes in mind.</p>
<p>I don&#8217;t think this will replace branding via features &#8211; it still can&#8217;t make changes to the layout of your pages, beyond what can be achieved with CSS &#8211; but it does address a number of the pain points with 2007 Themes. Certainly, it&#8217;s something I can see being useful for those customers wanting SharePoint to &#8220;just not look SharePointy&#8221; without having to go to the pain of development.</p>
<p>Though they will have to choose decent colors!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.novolocus.com/2010/04/14/themes-in-sharepoint-2010/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Hide a custom field from the Document Information Panel</title>
		<link>http://www.novolocus.com/2010/04/13/hide-a-custom-field-from-the-dip/</link>
		<comments>http://www.novolocus.com/2010/04/13/hide-a-custom-field-from-the-dip/#comments</comments>
		<pubDate>Tue, 13 Apr 2010 21:08:47 +0000</pubDate>
		<dc:creator>Andy</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Document Information Panel]]></category>
		<category><![CDATA[SPField]]></category>
		<category><![CDATA[xml]]></category>

		<guid isPermaLink="false">http://www.novolocus.com/?p=1803</guid>
		<description><![CDATA[So, I&#8217;ve been working with a custom field type recently. It&#8217;s quite a complicated one &#8211; I&#8217;ll not go into details &#8211; but we did hit a problem with it. When a Word document was opened it would try to display our field in the Document Information Panel, which isn&#8217;t really possible, and caused Word [...]]]></description>
			<content:encoded><![CDATA[<p>So, I&#8217;ve been working with a custom field type recently. It&#8217;s quite a complicated one &#8211; I&#8217;ll not go into details &#8211; but we did hit a problem with it. When a Word document was opened it would try to display our field in the <a href="http://www.razorleaf.com/2010/03/dip-and-sharepoint/">Document Information Panel</a>, which isn&#8217;t really possible, and caused Word to die in a horrible fashion. I forget the exact error we were getting, but it was something to do with the XSN being invalid.</p>
<p>What we really needed was a way to set that the property wasn&#8217;t to be shown in the Document Information Panel. However, there is no easy way of doing this with a purely programmatically created column. There are properties on the<strong> </strong><a href="http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.spfield_members(v=office.12).aspx"><strong>SPField</strong> </a>object that can be accessed programmatically, and the <a href="http://msdn.microsoft.com/en-us/library/aa543225.aspx">CAML for a FieldRef </a>can set <em>ShowInFileDlg</em> &#8211; but there isn&#8217;t an obvious way to set this value from C# code.</p>
<p>Naturally, that&#8217;s what we wanted to do. Well, there is a combination approach &#8211; the <a href="http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.spfield.schemaxml(v=office.12).aspx"><strong>SPField.SchemaXml</strong> </a>property allows us to get/set the CAML that defines the field.</p>
<p>So, I came up with this static function:</p>
<pre class="brush: csharp;">static void SetShowInFileDlg(SPField f, bool value)
        {
            XmlDocument fieldSchemaXml = new XmlDocument();
            fieldSchemaXml.LoadXml(f.SchemaXml);
            XmlAttribute attr = fieldSchemaXml.CreateAttribute(&quot;ShowInFileDlg&quot;);
            attr.Value = value.ToString().ToUpper();
            XmlNode fieldXmlNode = fieldSchemaXml.SelectSingleNode(&quot;Field&quot;);
            XmlAttributeCollection fieldAttributes = fieldXmlNode.Attributes;
            fieldAttributes.Append(attr);
           
            f.SchemaXml = fieldXmlNode.OuterXml;
            f.Update(true);
        }</pre>
<p>I&#8217;m not sure what happens if you&#8217;re trying to update an already widely used column &#8211; will it update all content types that that column &#8211; but this worked for us.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.novolocus.com/2010/04/13/hide-a-custom-field-from-the-dip/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Date Formats in XSL with ddwrt</title>
		<link>http://www.novolocus.com/2010/04/12/date-formats-in-xsl-with-ddwrt/</link>
		<comments>http://www.novolocus.com/2010/04/12/date-formats-in-xsl-with-ddwrt/#comments</comments>
		<pubDate>Mon, 12 Apr 2010 15:07:50 +0000</pubDate>
		<dc:creator>Andy</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Dates]]></category>
		<category><![CDATA[XSL]]></category>

		<guid isPermaLink="false">http://www.novolocus.com/?p=1800</guid>
		<description><![CDATA[Previously I&#8217;ve blogged about using ddwrt to format dates and datetimes. Well, today, I found myself trying to figure it out again, so here is a reminder. Remember, one of the big advantages of this (in the UK at least, where we are UTC time half the year) is that the DateFormat function accounts for [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.novolocus.com/2009/03/26/date-formats-in-sharepoint-again/">Previously</a> I&#8217;ve blogged about using <strong>ddwrt</strong> to format dates and datetimes. Well, today, I found myself trying to figure it out again, so here is a reminder. Remember, one of the big advantages of this (in the UK at least, where we are UTC time half the year) is that the DateFormat function accounts for daylight savings (i.e. the difference between GMT and BST)</p>
<p>Add this to the <strong>xsl:stylesheet</strong> tag at the top:</p>
<pre class="brush: xml;">xmlns:ddwrt=&quot;http://schemas.microsoft.com/WebParts/v2/DataView/runtime&quot;</pre>
<p>Then you can use something like the following (where item_date is an XSL variable with our date in it):</p>
<pre class="brush: xml;">&lt;xsl:value-of select=&quot;ddwrt:FormatDate(string($item_date), 2057, 15)&quot; /&gt;</pre>
<p>Here the FormatDate function is taking the string of the date, formating it for Great Britain&#8217;s locale (2057), and specifying an output format (15). Output formats vary by locale, and not all seem to be valid. I found that when I tried a format of &#8216;2&#8242;, for example, that I got an XSL error.</p>
<p>This is a particularly useful with the Content Query Web Part and the RSS Feed Web Part</p>
]]></content:encoded>
			<wfw:commentRss>http://www.novolocus.com/2010/04/12/date-formats-in-xsl-with-ddwrt/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Curious case of Microsoft.Office.Server.ServerContext.Current</title>
		<link>http://www.novolocus.com/2010/03/18/curious-case-of-microsoft-office-server-servercontext-current/</link>
		<comments>http://www.novolocus.com/2010/03/18/curious-case-of-microsoft-office-server-servercontext-current/#comments</comments>
		<pubDate>Thu, 18 Mar 2010 12:45:10 +0000</pubDate>
		<dc:creator>Andy</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[SharePoint 2007]]></category>
		<category><![CDATA[ServerContext]]></category>

		<guid isPermaLink="false">http://www.novolocus.com/?p=1787</guid>
		<description><![CDATA[So, this is the weirdest bug I&#8217;ve seen in quite some time. I&#8217;d inherited some code, which includes a settings page in the _layouts directory. It&#8217;s a pretty normal page &#8211; nothing particularly bad about it, and it seemed to work nicely. Then I received a call about an error with it:

Now, here is the [...]]]></description>
			<content:encoded><![CDATA[<p>So, this is <em>the</em> weirdest bug I&#8217;ve seen in quite some time. I&#8217;d inherited some code, which includes a settings page in the <em>_layouts</em> directory. It&#8217;s a pretty normal page &#8211; nothing particularly bad about it, and it seemed to work nicely. Then I received a call about an error with it:</p>
<p><a href="http://www.novolocus.com/wp-content/uploads/2010/03/ServerContext-Error.png"><img class="alignnone size-medium wp-image-1790" title="ServerContext Error" src="http://www.novolocus.com/wp-content/uploads/2010/03/ServerContext-Error-300x56.png" alt="" width="300" height="56" /></a><a href="http://www.novolocus.com/wp-content/uploads/2010/03/ServerContext-Error.png"></a></p>
<p>Now, here is the weird thing. When I started to examine it, I tried to replicate the problem. And I realised that <strong>the page worked when I accessed it from the server, but threw an ArgumentNullException when I accessed it from a client</strong>.</p>
<p>Yes, you read that right. <strong>What machine you browsed to the page on mattered</strong>. The browsers were the same. The code worked when viewed on the server, and failed when viewed from the client. When I eventually fixed it, I swapped between the broken and fixed code a few times to prove it &#8211; this really was the behaviour!<span id="more-1787"></span></p>
<p>I can only hope there is another factor I&#8217;ve not considered, &#8216;cos I don&#8217;t get how that can be the case.</p>
<p>The error message was:</p>
<blockquote><p>Value cannot be null.<br />
Parameter name: serverContext   at Microsoft.Office.Server.UserProfiles.UserProfileManager..ctor(ServerContext serverContext, Boolean IgnoreUserPrivacy, Boolean backwardCompatible)<br />
   at Microsoft.Office.Server.UserProfiles.UserProfileManager..ctor(ServerContext serverContext)<br />
   at MyAssembly.Pages.SettingsPage.OnLoad(EventArgs e)<br />
   at System.Web.UI.Control.LoadRecursive()<br />
   at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)</p></blockquote>
<p>Looking in my code, I only had one call to the <a href="http://msdn.microsoft.com/en-us/library/microsoft.office.server.userprofiles.userprofilemanager.aspx"><strong>UserProfileManager</strong> </a>constructor:</p>
<pre class="brush: csharp;">UserProfileManager oMgr = new UserProfileManager(ServerContext.Current);</pre>
<p><a href="http://msdn.microsoft.com/en-us/library/microsoft.office.server.servercontext.aspx"><strong>ServerContext</strong> </a>is in a SharePoint assembly, so it was out with reflector:</p>
<p><a href="http://www.novolocus.com/wp-content/uploads/2010/03/ServerContext.Current.png"><img class="alignnone size-medium wp-image-1789" title="ServerContext.Current" src="http://www.novolocus.com/wp-content/uploads/2010/03/ServerContext.Current-300x54.png" alt="" width="300" height="54" /></a></p>
<p>Ok, so we&#8217;re just calling <a href="http://msdn.microsoft.com/en-us/library/microsoft.office.server.servercontext.getcontext.aspx"><strong>GetContext()</strong> </a>with the <strong>HttpContext</strong>. What goes on in there? This mess&#8230;</p>
<p><a href="http://www.novolocus.com/wp-content/uploads/2010/03/ServerContext.GetContext.png"><img class="alignnone size-medium wp-image-1791" title="ServerContext.GetContext" src="http://www.novolocus.com/wp-content/uploads/2010/03/ServerContext.GetContext-300x164.png" alt="" width="300" height="164" /></a></p>
<p>Yes, it&#8217;s nice and easy to figure out the logic of what&#8217;s going on in there. The short of it is that I saw several ways of NULL being returned &#8211; which would then cause our error.</p>
<p>So, my solution? Well, I didn&#8217;t like that mess, so I tried a different<a href="http://msdn.microsoft.com/en-us/library/microsoft.office.server.servercontext.getcontext.aspx"> <strong>GetContext()</strong> </a>method.</p>
<pre class="brush: csharp;">UserProfileManager oMgr = new UserProfileManager(ServerContext.GetContext(this.Site));</pre>
<p>This worked when browsed to on either client or server. I chose that overload as it is <em>much</em> simpler, and doesn&#8217;t seem to rely at all on the <strong>HttpContext</strong> at all</p>
<p>Further research showed that <a href="http://social.msdn.microsoft.com/Forums/en-US/sharepointdevelopment/thread/6dc9d581-2cb9-43ce-ab9e-48e24dd1a171?prof=required">other people have seem the same strange behaviour</a>. <a href="http://social.msdn.microsoft.com/Forums/en-US/sharepointdevelopment/thread/68a12fb0-692b-4bfb-b6b5-b2d03e4098f7">Repeatedly</a>. And the issue may be related to <a href="http://blog.ozo.dk/?p=60">how the ServerContext is initialised</a>.</p>
<p>I still don&#8217;t get how it can be different between the client and server, though. Post your ideas here!</p>
<p><strong>EDIT:</strong> Ah-ha! Evidence that the problem is <a href="http://lanestechblog.blogspot.com/2008/03/value-cannot-be-null-error-when-trying.html">related to the Alternate Access Mappings</a>. And a <a href="http://babelfish.yahoo.com/translate_url?doit=done&amp;tt=url&amp;intl=1&amp;fr=bf-home&amp;trurl=http%3A%2F%2Fwww.obablog.de%2FLists%2FBeitraege%2FPost.aspx%3FID%3D34&amp;lp=de_en">German blog post suggesting the same</a>. And that would explain why the difference between client and server.</p>
<p>To check, I reverted my code back to it&#8217;s original form &#8211; and the exception reappeared. I then added another AAM:</p>
<p><a href="http://www.novolocus.com/wp-content/uploads/2010/03/AAM.png"><img class="alignnone size-medium wp-image-1798" title="AAM" src="http://www.novolocus.com/wp-content/uploads/2010/03/AAM-300x72.png" alt="" width="300" height="72" /></a></p>
<p>The Extranet one is what I added &#8211; and suddenly the error went away &#8211; and my code worked. Interesting.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.novolocus.com/2010/03/18/curious-case-of-microsoft-office-server-servercontext-current/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SUGUK Meeting on the 11th March</title>
		<link>http://www.novolocus.com/2010/03/17/suguk-meeting-11mar/</link>
		<comments>http://www.novolocus.com/2010/03/17/suguk-meeting-11mar/#comments</comments>
		<pubDate>Wed, 17 Mar 2010 13:18:11 +0000</pubDate>
		<dc:creator>Andy</dc:creator>
				<category><![CDATA[Business Intelligence]]></category>
		<category><![CDATA[Suguk]]></category>

		<guid isPermaLink="false">http://www.novolocus.com/?p=1784</guid>
		<description><![CDATA[Right, so I&#8217;m finally taking a lunchtime to write up about the SUGUK Meeting in London last Thursday. The topic was Business Intelligence in SharePoint 2010, and the main presentation was by Ben Robb, with a discussion afterwards. It covered a lot of technologies &#8211; there are a lot you can use &#8211; but the [...]]]></description>
			<content:encoded><![CDATA[<p>Right, so I&#8217;m finally taking a lunchtime to write up about the SUGUK Meeting in London last Thursday. The topic was Business Intelligence in SharePoint 2010, and the main presentation was by <a href="http://sharepointtales.wordpress.com/">Ben Robb</a>, with a discussion afterwards. It covered a lot of technologies &#8211; there are a lot you can use &#8211; but the bit that I think will be interesting is the methodology and management. <span id="more-1784"></span></p>
<p>Ben started by discussing the why of BI, and the tools available. There are quite a lot &#8211; SQL Reporting Services, Excel Services, Business Data Catalog (sorry, <em>Business Connectivity Services</em> now!), KPIs in SharePoint.</p>
<p>The crux of this point was that ultimately, you want to empower business users to report on data they think is relevant. You don&#8217;t want to have to employ developers to build these things &#8211; <em>they</em> don&#8217;t know the data, or what figures are important. It&#8217;s a fair point. The sidebar to that is that you do need technical staff to get the data into your &#8216;cube&#8217; in the first place. In other words, data has to be drawn into a central location and structured there, and then end users can generate the metrics they want from that.</p>
<p>His demo was, frankly, a bit of a stunner. Drilling down through what was clearly a large data-set, sorting and filtering millions of rows to show off <a href="http://www.powerpivot.com/">PowerPivot </a>(no, I still don&#8217;t really get what it is). The Decomposition Tree was very neat. Definite &#8216;wow&#8217; factor, with a bit of a message of &#8216;just slap a few web parts on, and it works&#8217;.</p>
<p>And that last point was what stuck out for me. Yes, the demo was very impressive. Plenty of charts, filtering, drilling down, publishing to Excel, Bing maps. Slapping web parts on the page looked very simple. But it all relies on you having put your data into an <a href="http://en.wikipedia.org/wiki/OLAP_cube">OLAP cube</a>. Don&#8217;t know what one of those is? No, me neither (and I was very glad when Chris O&#8217;Brien asked what they were &#8211; I was assuming <em>everyone else</em> knew!)</p>
<p>When we then started talking about how to draw in that data, the message really became one of &#8220;Plan, Plan, Be methodical and Take Your Time&#8221;. That rather sits at odds with the demo. Building your data model does need to be done carefully, but it&#8217;s not visible, it&#8217;s not sexy, and it&#8217;s not interesting to management/end users. They just want pretty charts. So you&#8217;ve got this tension between the user interface end being &#8220;Fast, Easy, POW &#8211; Done&#8221; and the back end being &#8220;Careful, Plan, Gently&#8221;. I&#8217;m worried that Microsoft&#8217;s marketing &#8211; and salesmen throughout the industry &#8211; will set an expectation which can&#8217;t be easily met.</p>
<p>Of course, if you&#8217;ve already got a nice OLAP cube to use, that&#8217;s not an issue. But the other elephant in the room was that most companies don&#8217;t have that. Reporting is an afterthought. At best you get Requests for Tender that say you &#8216;must be able to produce reports&#8217;, but the dialog then goes:</p>
<p><em>&#8220;Report on what?&#8221;</em></p>
<p><em>&#8220;Um, anything we want&#8221;</em></p>
<p>Sometimes reporting isn&#8217;t mentioned at all. And when there is reporting, what is the most ubiquitous reporting tool around? Excel Spreadsheets. Every organisation has lots invested in Excel spreadsheets for reporting. And it&#8217;s all very well to say &#8220;<em>Ah-ha! Excel Services!</em>&#8221; &#8211; but now tell me how to deal with linked spreadsheets? Or VBA Macros? They <em>always</em> make an appearance, and it&#8217;s a phenomenally hard thing to deal with short of &#8216;right, let&#8217;s start again with a different technology&#8217;, which is hard to do without a feeling of reinventing the wheel. That&#8217;s not to say that I don&#8217;t think it should be done &#8211; but it&#8217;s a tough sell.</p>
<p>All of which then leads round the methodology of this, and the change management &#8211; which was a bit outside what could be covered in the meeting. This is where things will get interesting, though &#8211; controlling the vision of what can be achieved, and then managing the changes to the existing reporting strategy. Especially as people do like (or maybe just &#8216;know&#8217;) Excel. But that&#8217;s for  later post &#8211; or maybe just someone who knows more.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.novolocus.com/2010/03/17/suguk-meeting-11mar/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Make Visual Studio break on all Exceptions</title>
		<link>http://www.novolocus.com/2010/02/08/make-visual-studio-break-on-all-exceptions/</link>
		<comments>http://www.novolocus.com/2010/02/08/make-visual-studio-break-on-all-exceptions/#comments</comments>
		<pubDate>Mon, 08 Feb 2010 08:00:22 +0000</pubDate>
		<dc:creator>Andy</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Visual Studio]]></category>

		<guid isPermaLink="false">http://www.novolocus.com/?p=1782</guid>
		<description><![CDATA[I&#8217;m a big fan of not raising exceptions if possible &#8211; rather than throwing and catching &#8216;expected exceptions&#8217;. To me, that phrase is an oxymoron &#8211; exceptions should be, um, exceptional, and it can make the wood hard to see for the trees when looking for proper exceptions.
Anyway, that aside &#8211; you can make Visual [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m a big fan of not raising exceptions if possible &#8211; rather than throwing and catching &#8216;expected exceptions&#8217;. To me, that phrase is an oxymoron &#8211; exceptions should be, um, exceptional, and it can make the wood hard to see for the trees when looking for proper exceptions.</p>
<p>Anyway, that aside &#8211; you can make Visual Studio break on any exception, not just the unhandled ones. Use Ctrl-Alt-E to edit &#8211; there is supposed to be some way to get to it though the menu, but I&#8217;ve not found it. Discovered in a <a href="http://stevesmithblog.com/blog/visual-studio-break-when-exception-thrown/">blog post here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.novolocus.com/2010/02/08/make-visual-studio-break-on-all-exceptions/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Breadcrumbs in Central Admin and Application Pages</title>
		<link>http://www.novolocus.com/2010/02/05/breadcrumbs-in-central-admin-and-application-pages/</link>
		<comments>http://www.novolocus.com/2010/02/05/breadcrumbs-in-central-admin-and-application-pages/#comments</comments>
		<pubDate>Fri, 05 Feb 2010 08:22:31 +0000</pubDate>
		<dc:creator>Andy</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Application Pages]]></category>
		<category><![CDATA[Breadcrumbs]]></category>
		<category><![CDATA[Central Admin]]></category>
		<category><![CDATA[Navigation]]></category>

		<guid isPermaLink="false">http://www.novolocus.com/?p=1779</guid>
		<description><![CDATA[This is a reminder of a couple of problems that I&#8217;ve come across a few times &#8211; that the breadcrumbs in LAYOUTS pages and central admin are a bit tricky.
Breadcrumbs in Layouts pages are driven by an XML file in your IIS web app. Now, you can add entries which are merged into that &#8211; a [...]]]></description>
			<content:encoded><![CDATA[<p>This is a reminder of a couple of problems that I&#8217;ve come across a few times &#8211; that the breadcrumbs in LAYOUTS pages and central admin are a bit tricky.</p>
<p>Breadcrumbs in Layouts pages are driven by an XML file in your IIS web app. Now, you can add entries which are merged into that &#8211; a described by Jan Tielens&#8217; <a href="http://weblogs.asp.net/jan/archive/2008/04/16/adding-breadcrumb-navigation-to-sharepoint-application-pages-the-easy-way.aspx">Adding Breadcrumb to application pages in SharePoint &#8211; the easy way</a>. However, this doesn&#8217;t cover the whole problem &#8211; he goes on to describe <a href="http://weblogs.asp.net/jan/archive/2008/10/10/adding-breadcrumb-navigation-to-application-pages-in-sharepoint-central-administration.aspx">dealing with Central Admin </a>too.</p>
<p>However, the really tricky bit of this that though we can define our own sitemap.xml file, it&#8217;s kind of hard to merge with the existing one. Specifically, the problem is that to merge &#8216;our additions&#8217; and the &#8216;existing file&#8217;, we have to call a function <strong><a href="http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.administration.spwebservice.applyapplicationcontenttolocalserver.aspx">ApplyApplicationContentToLocalServer</a></strong>, and as <a href="http://sharepointinterface.com/2009/06/06/the-applyapplicationcontenttolocalserver-method-and-why-it-comes-up-short/">brilliantly described by Sean McDonough</a>, the word &#8216;local&#8217; is a problem in this method &#8211; it only forces a merge of the files on one server. Not much use in a server farm.</p>
<p>Sean&#8217;s article describes his attempt at a fix &#8211; <a href="http://blobcachefarmflush.codeplex.com/SourceControl/changeset/view/53851#856355">using a one-time timer job</a>, and a fair bit of reverse engineering of the <strong>ApplyApplicationContentToLocalServer</strong> function. Also, it seems like Vince Rothwell has come up with <a href="http://blog.thekid.me.uk/archive/2007/01/17/configuring-the-breadcrumb-for-pages-in-layouts.aspx">a similar solution</a>, so it&#8217;s likely that this is a good approach.</p>
<p>A real pain to have to build so much to do such a simple task, though.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.novolocus.com/2010/02/05/breadcrumbs-in-central-admin-and-application-pages/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Application Master Page Changer Project</title>
		<link>http://www.novolocus.com/2009/12/29/application-master-page-changer-project/</link>
		<comments>http://www.novolocus.com/2009/12/29/application-master-page-changer-project/#comments</comments>
		<pubDate>Tue, 29 Dec 2009 10:00:36 +0000</pubDate>
		<dc:creator>Andy</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Application Pages]]></category>
		<category><![CDATA[HTTPModule]]></category>
		<category><![CDATA[Master Pages]]></category>

		<guid isPermaLink="false">http://www.novolocus.com/?p=1751</guid>
		<description><![CDATA[The product of many evenings in hotels recently, I&#8217;m proud to present, my Application Master Page Changer.
Application master pages are tricky &#8211; out of the box in SharePoint 2007, there is no way of changing the master page used for &#8216;administrative&#8217; pages. Unfortunately, those administrative pages include things like the recycle bin, file upload, and [...]]]></description>
			<content:encoded><![CDATA[<p>The product of many evenings in hotels recently, I&#8217;m proud to present, my Application Master Page Changer.</p>
<p><a href="http://www.novolocus.com/2008/08/18/pages-in-sharepoint-v-application-pages/">Application master pages are tricky</a> &#8211; out of the box in SharePoint 2007, there is no way of changing the master page used for &#8216;administrative&#8217; pages. Unfortunately, those administrative pages include things like the recycle bin, file upload, and the &#8216;View all site content&#8217; pages &#8211; things that users will likely see.</p>
<p>Well, folks have found <a href="http://www.novolocus.com/2007/09/26/using-a-different-master-page-on-application-pages/">a solution to this</a> -  using an <a href="http://msdn.microsoft.com/en-us/library/bb398986.aspx"><strong>HTTPModule</strong> </a>to intercept pages using the normal <em>application.master</em> and redirecting it to use your custom one. This works pretty well, but I was always a bit uncomfortable &#8211; what if you only want this to happen for particular site collections, or specific sites within a Web Application? I&#8217;d tried knocking up an <strong>HTTPModule</strong> to do this, but matching against URLs &#8211; bit it was awkward to configure, complex, and adding new sites/site collections could be a bit annoying &#8211; basically, a nightmare to configure.</p>
<p>What we really need, I thought, is some way of just turning on/off the master pages being used with Features. And that&#8217;s what I&#8217;ve built. <a href="http://www.novolocus.com/software/application-master-page-changer/">Check it out here&#8230;</a></p>
<p><a href="http://www.novolocus.com/wp-content/uploads/2009/12/Feature-Activated-and-Master-page-changed.png"><img class="alignnone size-medium wp-image-1757" title="Feature Activated and Master page changed" src="http://www.novolocus.com/wp-content/uploads/2009/12/Feature-Activated-and-Master-page-changed-300x94.png" alt="" width="300" height="94" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.novolocus.com/2009/12/29/application-master-page-changer-project/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Adding and removing Web config modifications</title>
		<link>http://www.novolocus.com/2009/12/24/adding-and-removing-web-config-modifications/</link>
		<comments>http://www.novolocus.com/2009/12/24/adding-and-removing-web-config-modifications/#comments</comments>
		<pubDate>Thu, 24 Dec 2009 13:49:45 +0000</pubDate>
		<dc:creator>Andy</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[SPWebConfigModification]]></category>

		<guid isPermaLink="false">http://www.novolocus.com/?p=1745</guid>
		<description><![CDATA[When building an application for SharePoint, if you&#8217;re making changes to the Web.config, they should be deployed SPWebconfigModifications. This isn&#8217;t that easy, really, but works well enough, and there are good articles about how to add them &#8211; but my code looks like:
SPWebConfigModification modification = new SPWebConfigModification(
     &#34;add[@name='MyNavProvider']&#34;,
     [...]]]></description>
			<content:encoded><![CDATA[<p>When building an application for SharePoint, if you&#8217;re making changes to the Web.config, they should be deployed <a href="http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.administration.spwebconfigmodification.aspx"><strong>SPWebconfigModifications</strong></a>. This isn&#8217;t that easy, really, but works well enough, and there are <a href="http://daniellarson.spaces.live.com/Blog/cns!D3543C5837291E93!916.entry">good</a> <a href="http://sharepointsolutions.blogspot.com/2006/12/using-spwebconfigmodificat_116736917110571614.html">articles</a> about how to add them &#8211; but my code looks like:</p>
<pre class="brush: csharp;">SPWebConfigModification modification = new SPWebConfigModification(
     &quot;add[@name='MyNavProvider']&quot;,
     &quot;configuration/system.web/siteMap/providers&quot;);
modification.Value = &quot;&lt;add name=\&quot;MyNavProvider\&quot; type=\&quot;{Assembly info here!}\&quot; /&gt;&quot;;;
modification.Sequence = 0;
modification.Type = SPWebConfigModification.SPWebConfigModificationType.EnsureChildNode;
modification.Owner = &quot;MyConfigModification;

webApp.WebConfigModifications.Add(modification);
webApp.Update();</pre>
<p>That works, but what about removing them? It&#8217;s important to do this &#8211; otherwise you can cripple a system. <span id="more-1745"></span>Well, I basically do the same as <a href="http://blog.thekid.me.uk/archive/2007/03/20/removing-web-config-entries-from-sharepoint-using-spwebconfigmodification.aspx">Vincent Rothwell</a> &#8211; loop through the existing modifications finding ones with the correct owner, then then delete them.</p>
<p>However, I did have a problem the other day which took hours to track down. When I tried to remove my <strong>SPWebConfigModification</strong>, it would be removed &#8211; but the XML remained in my web.config. Eventually I realised something pretty obvious -the &#8216;name&#8217; is really part of an XPath query used to find the node we&#8217;d added, in order to remove it. From MSDN:</p>
<blockquote><p>When the type of web.config modification is EnsureChildNode, the <a href="http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.administration.spwebconfigmodification.name.aspx">Name </a>property refers to an XPath expression that uniquely identifies the node under the parent node, as identified by the Path property</p></blockquote>
<p>Therefore, the &#8216;name&#8217; in my Name property must match the &#8216;name&#8217; in the XML node I&#8217;d inserted in my web.config.</p>
<p><a href="http://www.novolocus.com/wp-content/uploads/2009/12/WebConfigMod.png"><img class="alignnone size-medium wp-image-1746" title="WebConfigMod" src="http://www.novolocus.com/wp-content/uploads/2009/12/WebConfigMod-300x48.png" alt="" width="300" height="48" /></a></p>
<p>Mine were different (though my own stupidity), so the Remove operation was trying to remove a different XML node to the one I&#8217;d added.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.novolocus.com/2009/12/24/adding-and-removing-web-config-modifications/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>More Problems with SharePoint Audit</title>
		<link>http://www.novolocus.com/2009/12/16/more-problems-with-sharepoint-audit/</link>
		<comments>http://www.novolocus.com/2009/12/16/more-problems-with-sharepoint-audit/#comments</comments>
		<pubDate>Wed, 16 Dec 2009 09:07:35 +0000</pubDate>
		<dc:creator>Andy</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Audit]]></category>
		<category><![CDATA[ListItem]]></category>

		<guid isPermaLink="false">http://www.novolocus.com/?p=1732</guid>
		<description><![CDATA[Right, more problems with Audit, in addition to problems mentioned previously. Although Updates to Documents have version numbers, updates to ListItems do not:
 
Interestingly, Deletes still have a version number. But there really is no version number recorded for updates&#8230;
 
&#8230; even when there is Versioning on the list:
 
Further, although previous versions of Documents have a url [...]]]></description>
			<content:encoded><![CDATA[<p>Right, <a href="http://www.novolocus.com/2009/11/26/observations-on-sharepoint-2007-audit/">more problems with Audit</a>, in addition to problems mentioned previously. Although Updates to <em>Documents</em> have version numbers, updates to <em>ListItems</em> do not:</p>
<p> <a href="http://www.novolocus.com/wp-content/uploads/2009/12/Delete-is-okay.PNG"><img class="alignnone size-medium wp-image-1733" title="Update is empty of Version info, while Delete is okay" src="http://www.novolocus.com/wp-content/uploads/2009/12/Delete-is-okay-300x34.PNG" alt="Update is empty of Version info, while Delete is okay" width="300" height="34" /></a></p>
<p>Interestingly, Deletes still have a version number. But there really is no version number recorded for updates&#8230;<span id="more-1732"></span></p>
<p> <a href="http://www.novolocus.com/wp-content/uploads/2009/12/No-Version-data-on-ListItem-Update.PNG"><img class="alignnone size-medium wp-image-1734" title="No Version data on ListItem Update" src="http://www.novolocus.com/wp-content/uploads/2009/12/No-Version-data-on-ListItem-Update-300x155.PNG" alt="No Version data on ListItem Update" width="300" height="155" /></a></p>
<p>&#8230; even when there is Versioning on the list:</p>
<p> <a href="http://www.novolocus.com/wp-content/uploads/2009/12/Version-History-works.PNG"><img class="alignnone size-medium wp-image-1735" title="Version History works" src="http://www.novolocus.com/wp-content/uploads/2009/12/Version-History-works-300x169.PNG" alt="Version History works" width="300" height="169" /></a><br />
Further, although previous versions of <em>Documents</em> have a url which includes the <strong>_vti_history</strong> folder, previous versions of <em>ListItems</em> do not &#8211; instead they just have a VersionNo <strong>GET</strong> parameter:</p>
<p> <a href="http://www.novolocus.com/wp-content/uploads/2009/12/ListItem-version-numbers-dealt-with-differently.PNG"><img class="alignnone size-medium wp-image-1736" title="ListItem version numbers dealt with differently" src="http://www.novolocus.com/wp-content/uploads/2009/12/ListItem-version-numbers-dealt-with-differently-300x151.PNG" alt="ListItem version numbers dealt with differently" width="300" height="151" /></a></p>
<p>In the VersionNo paramater, the Major version is <strong>(VersionNo DIV 512)</strong> and the Minor version is <strong>(VersionNo MOD 512)</strong> &#8211; <a href="http://vspug.com/dez/2007/11/30/moving-copying-documents-between-libraries-with-metadata-including-version-history/">thanks to Dink</a> for the hint on that part!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.novolocus.com/2009/12/16/more-problems-with-sharepoint-audit/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
