<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>Solutionizing .NET &#187; SharePoint</title>
	<atom:link href="http://solutionizing.net/category/sharepoint/feed/" rel="self" type="application/rss+xml" />
	<link>http://solutionizing.net</link>
	<description>Random thoughts on custom development in SharePoint.</description>
	<lastBuildDate>Fri, 03 Feb 2012 05:41:33 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='solutionizing.net' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://s2.wp.com/i/buttonw-com.png</url>
		<title>Solutionizing .NET &#187; SharePoint</title>
		<link>http://solutionizing.net</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://solutionizing.net/osd.xml" title="Solutionizing .NET" />
	<atom:link rel='hub' href='http://solutionizing.net/?pushpress=hub'/>
		<item>
		<title>SPWeb.AssociatedGroups.Contains Lies</title>
		<link>http://solutionizing.net/2010/01/27/spweb-associatedgroups-contains-lies/</link>
		<comments>http://solutionizing.net/2010/01/27/spweb-associatedgroups-contains-lies/#comments</comments>
		<pubDate>Wed, 27 Jan 2010 12:00:23 +0000</pubDate>
		<dc:creator>Keith Dahlby</dc:creator>
				<category><![CDATA[Object Model]]></category>
		<category><![CDATA[SharePoint]]></category>
		<category><![CDATA[extension method]]></category>
		<category><![CDATA[SPExLib]]></category>

		<guid isPermaLink="false">http://solutionizing.net/?p=537</guid>
		<description><![CDATA[While working on SPExLib (several months ago), I revisited this post, which presented a functional approach to a solution Adam describes here. Both posts include logic to add an SPWeb group association, which most simply could look something like this: SPGroup group = web.SiteGroups[groupName]; if (!web.AssociatedGroups.Contains(group)) { web.AssociatedGroups.Add(group); web.Update(); } While testing on a few [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=solutionizing.net&amp;blog=3982353&amp;post=537&amp;subd=solutionizing&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>While working on <a title="SPExLib Release: These Are A Few Of My Favorite Things" href="http://solutionizing.net/2009/06/01/spexlib-release-these-are-a-few-of-my-favorite-things/">SPExLib</a> (several months ago), I revisited <a title="More SharePoint Higher-Order Functions" href="http://solutionizing.net/2009/03/19/more-sharepoint-higher-order-functions/">this post</a>, which presented a functional approach to a solution Adam describes <a title="Get SPGroup, If Not Available, Create!" href="http://www.sharepointsecurity.com/blog/sharepoint/sharepoint-2007-development/get-spgroup-if-not-available-create/">here</a>. Both posts include logic to add an <code>SPWeb</code> group association, which most simply could look something like this:</p>
<pre>SPGroup group = web.SiteGroups[groupName];
if (!web.AssociatedGroups.Contains(group))
{
    web.AssociatedGroups.Add(group);
    web.Update();
}</pre>
<p>While testing on a few groups, I noticed that the <code>Contains()</code> call lies, always returning <code>false</code>. This behavior can also be verified with PowerShell:</p>
<pre>PS &gt; $w.AssociatedGroups | ?{ $_.Name -eq 'Designers' } | select Name

Name
----
Designers

PS &gt; $g = $w.SiteGroups['Designers']
PS &gt; $w.AssociatedGroups.Contains($g)
False</pre>
<p>Of course, it&#8217;s not actually lying&#8212;it just doesn&#8217;t do what we expect. Behind the scenes, <code>AssociatedGroups </code> is implemented as a simple <code>List&lt;SPGroup&gt;</code> that is populated with group objects retrieved by IDs stored in the <code>SPWeb</code>&#8216;s <code>vti_associategroups</code> property. The problem is that <code>List&lt;T&gt;.Contains()</code> uses <code>EqualityComparer&lt;T&gt;.Default</code> to find a suitable match, which defaults to reference equality for reference types like <code>SPGroup</code> that don&#8217;t implement <code>IEquatable&lt;T&gt;</code> or override <code>Equals()</code>.</p>
<p>To get around this, <a href="http://spexlib.codeplex.com/" title="SharePoint Extensions Lib">SPExLib</a> provides a few extension methods to make group collections and <code>SPWeb.AssociatedGroups</code> easier to work with and more closely obey the <a title="Principle of Least Astonishment - Wikipedia" href="http://en.wikipedia.org/wiki/Principle_of_least_astonishment">Principle of Least Surprise</a>:</p>
<pre>public static bool NameEquals(this SPGroup group, string name)
{
    return string.Equals(group.Name, name, StringComparison.OrdinalIgnoreCase);
}

public static bool Contains(this SPGroupCollection groups, string name)
{
    return groups.Any&lt;SPGroup&gt;(group =&gt; group.NameEquals(name));
}

public static bool HasGroupAssociation(this SPWeb web, string name)
{
    return web.AssociatedGroups.Contains(name);
}

public static bool HasGroupAssociation(this SPWeb web, SPGroup group)
{
    if (group == null)
        throw new ArgumentNullException("group");
    return web.HasGroupAssociation(group.Name);
}

public static void EnsureGroupAssociation(this SPWeb web, SPGroup group)
{
    if (web.HasGroupAssociation(group))
        web.AssociatedGroups.Add(group);
}</pre>
<p>The code should be pretty self-explanatory. The name comparison logic in <code>NameEquals()</code> is written to align with how SharePoint compares group names internally, though they use their own implementation of case insensitivity because the framework&#8217;s isn&#8217;t good enough. Or something like that.</p>
<p>There should be two lessons here:</p>
<ol>
<li>Don&#8217;t assume methods that have a notion of equality, like <code>Contains()</code>, will behave like you expect.</li>
<li>Use <a href="http://spexlib.codeplex.com/" title="SharePoint Extensions Lib">SPExLib</a> and contribute other extensions and helpers you find useful. :)</li>
</ol>
<br /> Tagged: extension method, SPExLib <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/solutionizing.wordpress.com/537/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/solutionizing.wordpress.com/537/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/solutionizing.wordpress.com/537/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/solutionizing.wordpress.com/537/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/solutionizing.wordpress.com/537/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/solutionizing.wordpress.com/537/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/solutionizing.wordpress.com/537/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/solutionizing.wordpress.com/537/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/solutionizing.wordpress.com/537/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/solutionizing.wordpress.com/537/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/solutionizing.wordpress.com/537/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/solutionizing.wordpress.com/537/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/solutionizing.wordpress.com/537/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/solutionizing.wordpress.com/537/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=solutionizing.net&amp;blog=3982353&amp;post=537&amp;subd=solutionizing&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://solutionizing.net/2010/01/27/spweb-associatedgroups-contains-lies/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/26483382e3717e58e4c45d06c8ec351d?s=96&#38;d=identicon&#38;r=PG" medium="image">
			<media:title type="html">dahlbyk</media:title>
		</media:content>
	</item>
		<item>
		<title>Functional Construction for ASP.NET Web Forms</title>
		<link>http://solutionizing.net/2009/09/13/functional-construction-for-asp-net-web-forms/</link>
		<comments>http://solutionizing.net/2009/09/13/functional-construction-for-asp-net-web-forms/#comments</comments>
		<pubDate>Sun, 13 Sep 2009 08:58:44 +0000</pubDate>
		<dc:creator>Keith Dahlby</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[WebParts & Controls]]></category>
		<category><![CDATA[Functional Construction]]></category>

		<guid isPermaLink="false">http://solutionizing.net/?p=647</guid>
		<description><![CDATA[System.Xml.Linq (a.k.a. LINQ to XML) introduces a nifty approach to creating XML elements called functional construction. I&#8217;m not entirely sure why they call it functional given that constructing an object graph is a decidedly non-functional task in the traditional sense of the word, but I digress. Functional construction has three key features: Constructors accept arguments [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=solutionizing.net&amp;blog=3982353&amp;post=647&amp;subd=solutionizing&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>System.Xml.Linq (a.k.a. LINQ to XML) introduces a nifty approach to creating XML elements called <a title="Functional Construction (LINQ to XML)" href="http://msdn.microsoft.com/en-us/library/bb387019.aspx">functional construction</a>. I&#8217;m not entirely sure why they call it functional given that constructing an object graph is a decidedly non-functional task in the traditional sense of the word, but I digress.</p>
<p>Functional construction has three key features:</p>
<ol>
<li>Constructors accept arguments of various types, handling them appropriately.</li>
<li>Constructors accept a <code>params</code> array of type <code>Object</code> to enable creation of complex objects.</li>
<li>If an argument implements <code>IEnumerable</code>, the objects within the sequence are added.</li>
</ol>
<p>If you haven&#8217;t seen it in action, I encourage you to take a look at the examples on MSDN and elsewhere—it really is pretty slick. This post will show how a similar technique can be used to build control trees in ASP.NET web forms (and probably WinForms with minimal adjustment).</p>
<p>Basic functional construction can be implemented using two relatively simple extension methods:</p>
<pre>public static void Add(this ControlCollection @this, object content)
{
    if (content is Control)
        @this.Add((Control)content);
    else if (content is IEnumerable)
        foreach (object c in (IEnumerable)content)
            @this.Add(c);
    else if (content != null)
        @this.Add(new LiteralControl(content.ToString()));
}

public static void Add(this ControlCollection @this, params object[] args)
{
    @this.Add((IEnumerable)args);
}</pre>
<p>We handle four cases:</p>
<ol>
<li>Control? Add it.</li>
<li>Sequence? Add each.</li>
<li>Other value? Add literal.</li>
<li>Null? Ignore.</li>
</ol>
<p>And our <code>params</code> overload just calls its arguments a sequence and defers to the other.</p>
<p>In the time-honored tradition of contrived examples:</p>
<pre>Controls.Add(
    new Label() { Text = "Nums:" },
    "&amp;nbsp;",
    from i in Enumerable.Range(1, 6)
    group i by i % 2
);</pre>
<p>This would render &#8220;Nums: 135246&#8243;. Note that the result of that LINQ expression is a sequence of sequences, which is flattened automatically and converted into literals. For comparison, here&#8217;s an equivalent set of statements:</p>
<pre>Controls.Add(new Label() { Text = "Nums:" });
Controls.Add(new LiteralControl("&amp;nbsp;"));
foreach (var g in from i in Enumerable.Range(1, 6)
                  group i by i % 2)
    foreach (var i in g)
        Controls.Add(new LiteralControl(i.ToString()));</pre>
<p>Hopefully seeing them side by side makes it clear why this new method of construction might have merit. But we&#8217;re not done yet.</p>
<h2>Expressions, Expressions, Expressions</h2>
<p>Many language features introduced in C# 3.0 and Visual Basic 9 make expressions increasingly important. By expressions I mean a single &#8220;line&#8221; of code that returns a value. For example, an object initializer is a single expression&#8230;</p>
<pre>var tb = new TextBox()
{
    ID = "textBox1",
    Text = "Text"
};</pre>
<p>&#8230; that represents several statements &#8230;</p>
<pre>var tb = new TextBox()
tb.ID = "textBox1";
tb.Text = "Text";</pre>
<p>That single TextBox expression can then be used in a number of places that its statement equivalent can&#8217;t: in another object initializer, in a collection initializer, as a parameter to a method, in a .NET 3.5 expression tree, the list goes on. Unfortunately, many older APIs simply aren&#8217;t built to work in an expression-based world. In particular, initializing subcollections is a considerable pain. However, we can extend the API to handle this nicely:</p>
<pre>public static T WithControls&lt;T&gt;(this T @this, params object[] content) where T : Control
{
    if(@this != null)
        @this.Controls.Add(content);
    return @this;
}</pre>
<p>The key is the return value: Control in, Control out. We can now construct and populate a container control with a single expression. For example, we could build a dictionary list (remember those?) from our groups:</p>
<pre>Controls.Add(
    new HtmlGenericControl("dl")
    .WithControls(
        from i in Enumerable.Range(1, 6)
        group i by i % 2 into g
        select new [] {
            new HtmlGenericControl("dt")
            { InnerText = g.Key == 0 ? "Even" : "Odd" },
            new HtmlGenericControl("dd")
            .WithControls(g)
        }
    )
);</pre>
<p>Which would render this:</p>
<blockquote><dl>
<dt>Odd</dt>
<dd>135</dd>
<dt>Even</dt>
<dd>246</dd>
</dl>
</blockquote>
<p>Without the ability to add controls within an expression, this result would require nested loops with local variables to store references to the containers. The actual code produced by the compiler would be nearly identical, but I find the expressions much easier to work with. Similarly, we can easily populate tables. Let&#8217;s build a cell per number:</p>
<pre>Controls.Add(
    new Table().WithControls(
        from i in Enumerable.Range(1, 6)
        group i by i % 2 into g
        select new TableRow().WithControls(
            new TableCell()
            { Text = g.Key == 0 ? "Even" : "Odd" },
            g.Select(n =&gt; new TableCell().WithControls(n))
        )
    )
);</pre>
<p>In a future post I&#8217;ll look at some other extensions we can use to streamline the construction and initialization of control hierarchies.</p>
<br /> Tagged: Functional Construction <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/solutionizing.wordpress.com/647/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/solutionizing.wordpress.com/647/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/solutionizing.wordpress.com/647/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/solutionizing.wordpress.com/647/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/solutionizing.wordpress.com/647/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/solutionizing.wordpress.com/647/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/solutionizing.wordpress.com/647/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/solutionizing.wordpress.com/647/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/solutionizing.wordpress.com/647/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/solutionizing.wordpress.com/647/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/solutionizing.wordpress.com/647/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/solutionizing.wordpress.com/647/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/solutionizing.wordpress.com/647/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/solutionizing.wordpress.com/647/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=solutionizing.net&amp;blog=3982353&amp;post=647&amp;subd=solutionizing&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://solutionizing.net/2009/09/13/functional-construction-for-asp-net-web-forms/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/26483382e3717e58e4c45d06c8ec351d?s=96&#38;d=identicon&#38;r=PG" medium="image">
			<media:title type="html">dahlbyk</media:title>
		</media:content>
	</item>
		<item>
		<title>Using IDisposables with LINQ</title>
		<link>http://solutionizing.net/2009/07/23/using-idisposables-with-linq/</link>
		<comments>http://solutionizing.net/2009/07/23/using-idisposables-with-linq/#comments</comments>
		<pubDate>Thu, 23 Jul 2009 08:28:29 +0000</pubDate>
		<dc:creator>Keith Dahlby</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[Object Model]]></category>
		<category><![CDATA[SharePoint]]></category>
		<category><![CDATA[AsSafeEnumerable]]></category>
		<category><![CDATA[IDisposable]]></category>
		<category><![CDATA[LINQ]]></category>
		<category><![CDATA[LINQ to SQL]]></category>

		<guid isPermaLink="false">http://solutionizing.net/?p=599</guid>
		<description><![CDATA[Objects that implement IDisposable are everywhere. The interface even gets its own language features (C#, VB, F#). However, LINQ throws a few wrenches into things: LINQ&#8217;s query syntax depends on expressions; using blocks are statements. When querying a sequence of IDisposable objects, there&#8217;s no easy way to ensure disposal after each element has been consumed. [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=solutionizing.net&amp;blog=3982353&amp;post=599&amp;subd=solutionizing&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Objects that implement <code>IDisposable</code> are everywhere. The interface even gets its own language features (<a title="using Statement (C# Reference)" href="http://msdn.microsoft.com/en-us/library/yh598w02.aspx">C#</a>, <a title="Using Statement (Visual Basic)" href="http://msdn.microsoft.com/en-us/library/htd05whh.aspx">VB</a>, <a title="Resource Management (F#)" href="http://msdn.microsoft.com/en-us/library/dd233240(VS.100).aspx">F#</a>). However, LINQ throws a few wrenches into things:</p>
<ol>
<li>LINQ&#8217;s query syntax depends on expressions; <code>using</code> blocks are statements.</li>
<li>When querying a sequence of <code>IDisposable</code> objects, there&#8217;s no easy way to ensure disposal after each element has been consumed.</li>
<li>Returning deferred queries from within a <code>using</code> statement is often desired, but fails spectacularly.</li>
</ol>
<p>There are possible work-arounds for each issue&#8230;</p>
<ol>
<li>Put the using statement in a method (named or anonymous) that is called from the query. See also: <a href="http://solutionizing.net/2009/02/20/thinking-functional-using/">Thinking Functional: Using</a>.</li>
<li>Use a method that creates a dispose-safe iterator of the sequence, like <a title="LINQ for SPWebCollection Revisited: AsSafeEnumerable" href="http://solutionizing.net/2009/01/05/linq-for-spwebcollection-revisited-assafeenumerable/">AsSafeEnumerable()</a>.</li>
<li>Refactor the method to inject the <code>IDisposable</code> dependency, as shown in the first part of Marc&#8217;s answer <a title="How does LINQ defer execution when in a using statement" href="http://stackoverflow.com/questions/456691/how-does-linq-defer-execution-when-in-a-using-statement/456698#456698">here</a>.</li>
</ol>
<p>But, as you might have guessed, I would like to propose a better solution. The code is really complex, so bear with me:</p>
<pre class="code">public static IEnumerable&lt;T&gt; Use&lt;T&gt;(this T obj) where T : IDisposable
{
    try
    {
        yield return obj;
    }
    finally
    {
        if (obj != null)
            obj.Dispose();
    }
}</pre>
<p>That&#8217;s it. We&#8217;re turning our <code>IDisposable</code> object into a single-element sequence. The trick is that the C# compiler will build an iterator for us that properly handles the <code>finally</code> clause, ensuring that our object will be disposed. It might be helpful to set a breakpoint on the <code>finally</code> clause to get a better idea what&#8217;s happening.</p>
<p>So how can this simple method solve all our problems? First up: &#8220;using&#8221; a <code>FileStream</code> object created in a LINQ query:</p>
<pre>var lengths = from path in myFiles
              from fs in File.OpenRead(path).Use()
              select new { path, fs.Length };</pre>
<p>Since the result of <code>Use()</code> is a single-element sequence, we can think of <code>from fs in something.Use()</code> as an assignment of that single value, <code>something</code>, to <code>fs</code>. In fact, it&#8217;s really quite similar to an F# <code>use</code> binding in that it will automatically clean itself up when it goes out of scope (by its enumerator calling <code>MoveNext()</code>).</p>
<p>Next, disposing elements from a collection. I&#8217;ll use the same SharePoint problem that <code>AsSafeEnumerable()</code> solves:</p>
<pre>var webs = from notDisposed in site.AllWebs
           from web in notDisposed.Use()
           select web.Title;</pre>
<p>I find this syntax rather clumsy compared with <code>AsSafeEnumerable()</code>, but it&#8217;s there if you need it.</p>
<p>Finally, let&#8217;s defer disposal of a LINQ to SQL <code>DataContext</code> until after the deferred query is executed, as an answer to the <a title="How does LINQ defer execution when in a using statement" href="http://stackoverflow.com/questions/456691/how-does-linq-defer-execution-when-in-a-using-statement">previously-linked Stack Overflow question</a>:</p>
<pre>IQueryable&lt;MyType&gt; MyFunc(string myValue)
{
    return from dc in new MyDataContext().Use()
           from row in dc.MyTable
           where row.MyField == myValue
           select row;
}

void UsingFunc()
{
    var result = MyFunc("MyValue").OrderBy(row =&gt; row.SortOrder);
    foreach(var row in result)
    {
        //Do something
    }
}</pre>
<p>The result of <code>MyFunc</code> now owns its destiny completely. It doesn&#8217;t depend on some potentially disposed <code>DataContext</code> &#8211; it just creates one that it will dispose when it&#8217;s done. There are probably situations where you would want to share a <code>DataContext</code> rather than create one on demand (I don&#8217;t use LINQ to SQL, I just blog about it), but again it&#8217;s there if you need it.</p>
<p>I&#8217;ve only started using this approach recently, so if you have any problems with it please share.</p>
<br /> Tagged: AsSafeEnumerable, IDisposable, LINQ, LINQ to SQL <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/solutionizing.wordpress.com/599/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/solutionizing.wordpress.com/599/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/solutionizing.wordpress.com/599/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/solutionizing.wordpress.com/599/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/solutionizing.wordpress.com/599/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/solutionizing.wordpress.com/599/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/solutionizing.wordpress.com/599/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/solutionizing.wordpress.com/599/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/solutionizing.wordpress.com/599/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/solutionizing.wordpress.com/599/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/solutionizing.wordpress.com/599/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/solutionizing.wordpress.com/599/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/solutionizing.wordpress.com/599/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/solutionizing.wordpress.com/599/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=solutionizing.net&amp;blog=3982353&amp;post=599&amp;subd=solutionizing&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://solutionizing.net/2009/07/23/using-idisposables-with-linq/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/26483382e3717e58e4c45d06c8ec351d?s=96&#38;d=identicon&#38;r=PG" medium="image">
			<media:title type="html">dahlbyk</media:title>
		</media:content>
	</item>
		<item>
		<title>Stylish Gears: Customizing SPLongOperation</title>
		<link>http://solutionizing.net/2009/07/03/stylish-gears-customizing-splongoperation/</link>
		<comments>http://solutionizing.net/2009/07/03/stylish-gears-customizing-splongoperation/#comments</comments>
		<pubDate>Fri, 03 Jul 2009 22:30:05 +0000</pubDate>
		<dc:creator>Keith Dahlby</dc:creator>
				<category><![CDATA[Object Model]]></category>
		<category><![CDATA[SharePoint]]></category>
		<category><![CDATA[SPLongOperation]]></category>

		<guid isPermaLink="false">http://solutionizing.net/?p=578</guid>
		<description><![CDATA[A frequently-asked branding question is how to customize the &#8220;gear&#8221; page shown during an SPLongOperation. The short answer is &#8220;you can&#8217;t&#8221;; but that&#8217;s not entirely true. The operation can be slightly customized using its LeadingHTML and TrailingHTML properties, which are written directly to the response stream. Because they aren&#8217;t encoded, we can use one to [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=solutionizing.net&amp;blog=3982353&amp;post=578&amp;subd=solutionizing&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>A frequently-asked branding question is how to customize the &#8220;gear&#8221; page shown during an <a title="Microsoft.SharePoint.SPLongOperation" href="http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.splongoperation.aspx">SPLongOperation</a>. The short answer is &#8220;you can&#8217;t&#8221;; but that&#8217;s not entirely true. The operation can be slightly customized using its <code>LeadingHTML</code> and <code>TrailingHTML</code> properties, which are written directly to the response stream. Because they aren&#8217;t encoded, we can use one to inject some JavaScript into the page that can manipulate the DOM, insert a stylesheet, really do anything we want. It&#8217;s not an ideal solution, as there will be a brief moment where the page is shown in its original form before the script can execute, but I believe it&#8217;s about the best we can do without directly modifying 12\TEMPLATE\LAYOUTS\gear.aspx. <img class="size-full alignright" src="http://solutionizing.files.wordpress.com/2009/07/gears_an.gif?w=780" alt="SharePoint's Gear of War"   /></p>
<p>As a quick proof of concept, here&#8217;s the source of an .aspx you can place in LAYOUTS to see a long operation page that uses the current theme:</p>
<pre>&lt;%@ Page Language="C#" %&gt;
&lt;%@ Import Namespace="Microsoft.SharePoint" %&gt;

&lt;script language="C#" runat="server"&gt;
  protected override void OnLoad(EventArgs e)
  {
    string themeUrl = SPContext.GetContext(this.Context).Web.ThemeCssUrl;
    using (SPLongOperation op = new SPLongOperation(this.Page))
    {
      StringBuilder sb = new StringBuilder();
      sb.Append(themeUrl+"&lt;/span&gt; \n");
      sb.Append("    &lt;script language=\"javascript\"&gt; \n");
      sb.Append("      (function(){ \n");
      sb.Append("        var objHead = document.getElementsByTagName('head')[0]; \n");
      sb.Append("        if(objHead) { \n");
      sb.Append("          var objTheme = objHead.appendChild(document.createElement('link')); \n");
      sb.Append("          objTheme.rel = 'stylesheet'; \n");
      sb.AppendFormat("          objTheme.href = '{0}'; \n", themeUrl);
      sb.Append("          objTheme.type = 'text/css'; \n");
      sb.Append("        } \n");
      sb.Append("      })();");
      sb.Append("\n&lt;"+"/script&gt;&lt;span&gt;");
      op.TrailingHTML = sb.ToString();
      op.Begin();

      System.Threading.Thread.Sleep(10000);
    }
  }
&lt;/script&gt;</pre>
<p>I use a <code>StringBuilder</code> because embedded scripts don&#8217;t play well with multi-line constants. In production, I would probably embed the script as a resource.</p>
<p>Here&#8217;s the result with the built-in Granite theme:<br />
<img class="size-full" title="ThemedLongOp" src="http://solutionizing.files.wordpress.com/2009/07/themedlongop.png?w=780" alt="Granite-Themed SPLongOperation"   /></p>
<br /> Tagged: SPLongOperation <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/solutionizing.wordpress.com/578/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/solutionizing.wordpress.com/578/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/solutionizing.wordpress.com/578/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/solutionizing.wordpress.com/578/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/solutionizing.wordpress.com/578/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/solutionizing.wordpress.com/578/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/solutionizing.wordpress.com/578/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/solutionizing.wordpress.com/578/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/solutionizing.wordpress.com/578/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/solutionizing.wordpress.com/578/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/solutionizing.wordpress.com/578/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/solutionizing.wordpress.com/578/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/solutionizing.wordpress.com/578/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/solutionizing.wordpress.com/578/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=solutionizing.net&amp;blog=3982353&amp;post=578&amp;subd=solutionizing&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://solutionizing.net/2009/07/03/stylish-gears-customizing-splongoperation/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/26483382e3717e58e4c45d06c8ec351d?s=96&#38;d=identicon&#38;r=PG" medium="image">
			<media:title type="html">dahlbyk</media:title>
		</media:content>

		<media:content url="http://solutionizing.files.wordpress.com/2009/07/gears_an.gif" medium="image">
			<media:title type="html">SharePoint&#039;s Gear of War</media:title>
		</media:content>

		<media:content url="http://solutionizing.files.wordpress.com/2009/07/themedlongop.png" medium="image">
			<media:title type="html">ThemedLongOp</media:title>
		</media:content>
	</item>
		<item>
		<title>Refactoring with LINQ &amp; Iterators: FindDescendantControl and GetDescendantControls</title>
		<link>http://solutionizing.net/2009/06/23/refactoring-with-linq-iterators-finddescendantcontrol-and-getdescendantcontrols/</link>
		<comments>http://solutionizing.net/2009/06/23/refactoring-with-linq-iterators-finddescendantcontrol-and-getdescendantcontrols/#comments</comments>
		<pubDate>Tue, 23 Jun 2009 06:37:51 +0000</pubDate>
		<dc:creator>Keith Dahlby</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[WebParts & Controls]]></category>
		<category><![CDATA[Iterators]]></category>
		<category><![CDATA[LINQ]]></category>
		<category><![CDATA[Refactor]]></category>

		<guid isPermaLink="false">http://solutionizing.net/?p=543</guid>
		<description><![CDATA[A while back I put together a quick and dirty implementation of a FindControl extension method: public static T FindControl&#60;T&#62;(this Control root, string id) where T : Control { Control c = root; Queue&#60;Control&#62; q = new Queue&#60;Control&#62;(); if (c == null &#124;&#124; c.ID == id) return c as T; do { foreach (Control child [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=solutionizing.net&amp;blog=3982353&amp;post=543&amp;subd=solutionizing&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>A while back I put together a <a title="User Profile MySite Redirect via Delegate Control" href="http://solutionizing.net/2008/12/08/user-profile-mysite-redirect-via-delegate-control/">quick and dirty implementation</a> of a <code>FindControl</code> extension method:</p>
<pre>public static T FindControl&lt;T&gt;(this Control root, string id) where T : Control
{
    Control c = root;
    Queue&lt;Control&gt; q = new Queue&lt;Control&gt;();

    if (c == null || c.ID == id)
        return c as T;
    do
    {
        foreach (Control child in c.Controls)
        {
            if (child.ID == id)
                return child as T;
            if (child.HasControls())
                q.Enqueue(child);
        }
        c = q.Dequeue();
    } while (c != null);
    return null;
}</pre>
<p>It got the job done (if the control exists!), but I think we can do better.</p>
<h2>Refactoring with Iterators</h2>
<p>My first concern is that the method is doing too much. Rather than searching for the provided ID, the majority of the code is devoted to navigating the control&#8217;s descendents. Let&#8217;s factor out that logic into its own method:</p>
<pre>public static IEnumerable&lt;Control&gt; GetDescendantControls(this Control root)
{
    var q = new Queue&lt;Control&gt;();

    var current = root;
    while (true)
    {
        if (current != null &amp;&amp; current.HasControls())
            foreach (Control child in current.Controls)
                q.Enqueue(child);

        if (q.Count == 0)
            yield break;

        current = q.Dequeue();
        yield return current;
    }
}</pre>
<p>The new method is almost as long as the old one, but now satisfies the <a href="http://en.wikipedia.org/wiki/Single_responsibility_principle">Single Responsibility Principle</a>. I also added a check to prevent calling <code>Dequeue()</code> on an empty queue. For those that have studied algorithms, note that this is a <a title="Breadth-First Search" href="http://en.wikipedia.org/wiki/Breadth-first_search">breadth-first</a> tree traversal.</p>
<p>Now we can update <code>FindControl</code>:</p>
<pre>public static T FindControl&lt;T&gt;(this Control root, string id) where T : Control
{
    Control c = root;

    if (c == null || c.ID == id)
        return c as T;

    foreach (Control child in c.GetDescendantControls())
    {
        if (child.ID == id)
            return child as T;
    }
    return null;
}</pre>
<p>With the control tree traversal logic extracted, this updated version is already starting to <a title="Code Smell" href="http://en.wikipedia.org/wiki/Code_smell">smell</a> better. But we&#8217;re not done yet.</p>
<h2>DRY? Don&#8217;t Repeat Someone Else, Either</h2>
<p>My second concern is how we&#8217;re checking for the ID in question. It&#8217;s not that the equality operator is a bad choice, as it will work in many scenarios, but rather that it&#8217;s not consistent with the existing <code>FindControl</code> method. In particular, the existing <code>FindControl</code> understands naming containers (IDs that contain &#8216;$&#8217; or &#8216;:&#8217;). Rather than implement our own comparison logic, we should just leverage the framework&#8217;s existing implementation:</p>
<pre>public static T FindControl&lt;T&gt;(this Control root, string id) where T : Control
{
    if (id == null)
        throw new ArgumentNullException("id");

    if (root == null)
        return null;

    Control c = root.FindControl(id);
    if (c != null)
        return c as T;

    foreach (Control child in c.GetDescendantControls())
    {
        c = child.FindControl(id);
        if (c != null)
            return child as T;
    }
    return null;
}</pre>
<p>Fun fact: <code>FindControl</code> will throw a <code>NullReferenceException</code> if <code>id</code> is <code>null</code>.</p>
<h2>Refactoring with LINQ</h2>
<p>So we have extracted the descendant logic and leaned on the framework for finding the controls, but I&#8217;m still not quite satisfied. The method just feels too&#8230;procedural. Let&#8217;s break down what we&#8217;re really trying to do:</p>
<ol>
<li>Look at the current control and all its descendants.</li>
<li>Use <code>FindControl</code> on each with the specified ID.</li>
<li>When we find the control, return it as type T.</li>
</ol>
<p>As the subheading might suggest, we can express these steps quite nicely with LINQ:</p>
<ol>
<li>
<pre>var controls = root.AsSingleton().Concat(root.GetDescendantControls());</pre>
</li>
<li>
<pre>var foundControls = from c in controls
                    let found = c.FindControl(id)
                    where found != null
                    select found;</pre>
</li>
<li>
<pre>return foundControls.FirstOrDefault() as T;</pre>
</li>
</ol>
<p>Behind the scenes, this is how I might have thought through this code:</p>
<ol>
<li>We use <code>AsSingleton()</code> (my new preferred name, to align with F#&#8217;s <code><a href="http://research.microsoft.com/en-us/um/cambridge/projects/fsharp/manual/fsharp.core/Microsoft.FSharp.Collections.Seq.html">Seq.singleton</a></code>, for <code>AsEnumerable()</code>, which I <a title="Generic Method Invocation with Expression Trees" href="http://solutionizing.net/2009/01/20/generic-method-invocation-with-expression-trees/">introduced here</a>) and <code>Concat()</code> to prepend <code>root</code> to the list of its descendants, returned as a lazy enumeration.</li>
<li>We use a query over those controls to retrieve matches from <code>FindControl()</code>, again returned as a lazy enumeration.</li>
<li>We grab the first control found, or <code>null</code> if none match, and return it <code>as T</code>.</li>
</ol>
<p>Because all our enumerations are lazy, we put off traversal of the entire control tree until we know we need to. In fact, if our ID is found in the root control, <code>GetDescendantControls()</code> won&#8217;t even be called! Through just a bit of refactoring, we have both an efficient and readable solution.</p>
<p>For completeness, here&#8217;s the final version with a more descriptive name to contrast with the existing <code>FindControl()</code>:</p>
<pre>public static T FindDescendantControl&lt;T&gt;(this Control root, string id) where T : Control
{
    if (id == null)
        throw new ArgumentNullException("id");

    if (root == null)
        return null;

    var controls = root.AsSingleton().Concat(root.GetDescendantControls());

    var foundControls = from c in controls
                        let found = c.FindControl(id)
                        where found != null
                        select found;

    return foundControls.FirstOrDefault() as T;
}</pre>
<p>I have added these methods, along with <code>AsSingleton()</code> and a host of others, to the <a href="http://www.codeplex.com/SPExLib">SharePoint Extensions Lib</a> project. Check it out!</p>
<br /> Tagged: Iterators, LINQ, Refactor <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/solutionizing.wordpress.com/543/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/solutionizing.wordpress.com/543/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/solutionizing.wordpress.com/543/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/solutionizing.wordpress.com/543/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/solutionizing.wordpress.com/543/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/solutionizing.wordpress.com/543/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/solutionizing.wordpress.com/543/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/solutionizing.wordpress.com/543/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/solutionizing.wordpress.com/543/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/solutionizing.wordpress.com/543/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/solutionizing.wordpress.com/543/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/solutionizing.wordpress.com/543/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/solutionizing.wordpress.com/543/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/solutionizing.wordpress.com/543/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=solutionizing.net&amp;blog=3982353&amp;post=543&amp;subd=solutionizing&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://solutionizing.net/2009/06/23/refactoring-with-linq-iterators-finddescendantcontrol-and-getdescendantcontrols/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/26483382e3717e58e4c45d06c8ec351d?s=96&#38;d=identicon&#38;r=PG" medium="image">
			<media:title type="html">dahlbyk</media:title>
		</media:content>
	</item>
		<item>
		<title>SPExLib Release: These Are A Few Of My Favorite Things</title>
		<link>http://solutionizing.net/2009/06/01/spexlib-release-these-are-a-few-of-my-favorite-things/</link>
		<comments>http://solutionizing.net/2009/06/01/spexlib-release-these-are-a-few-of-my-favorite-things/#comments</comments>
		<pubDate>Mon, 01 Jun 2009 07:22:16 +0000</pubDate>
		<dc:creator>Keith Dahlby</dc:creator>
				<category><![CDATA[Object Model]]></category>
		<category><![CDATA[Tools]]></category>
		<category><![CDATA[SPExLib]]></category>

		<guid isPermaLink="false">http://solutionizing.net/?p=532</guid>
		<description><![CDATA[It&#8217;s no secret that I&#8217;m a big fan of using extension methods to simplify work with the SharePoint object model. Wictor Wilén has allowed me to incorporate many of my &#8220;greatest hits&#8221; (and some new techniques! more on those in coming weeks) into his excellent SharePoint Extensions Lib project, which added a new release over [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=solutionizing.net&amp;blog=3982353&amp;post=532&amp;subd=solutionizing&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s no secret that I&#8217;m a big fan of using extension methods to simplify work with the SharePoint object model. <a href="http://www.wictorwilen.se/">Wictor Wilén</a> has allowed me to incorporate many of my &#8220;greatest hits&#8221; (and some new techniques! more on those in coming weeks) into his excellent <a href="http://SPExLib.CodePlex.com/">SharePoint Extensions Lib project</a>, which added a <a title="SharePoint Extensions Lib - Release: SPExLib 12.0.0.0" href="http://spexlib.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=28038">new release</a> over the weekend (also see Wictor&#8217;s <a title="New release for SPExLib with SharePoint Linq extensions" href="http://www.wictorwilen.se/Post/New-release-for-SPExLib-with-SharePoint-Linq-extensions.aspx">announcement</a>).</p>
<p>It&#8217;s also worth pointing out that this isn&#8217;t just a library of extension methods. It also includes some useful base controls and auxilary classes, including SPDisposeCheckIgnoreAttribute and SPDisposeCheckID with IntelliSense support. If you have classes or methods that you simply can&#8217;t live without, we&#8217;d love to incorporate them as well.</p>
<p>Additional reading on some of the extensions included:</p>
<ul>
<li><a rel="bookmark" href="http://solutionizing.net/2009/01/05/linq-for-spwebcollection-revisited-assafeenumerable/">LINQ for SPWebCollection Revisited: AsSafeEnumerable</a></li>
<li><a href="http://solutionizing.net/2009/01/06/elegant-spsite-elevation/">Elegant SPSite Elevation</a></li>
<li><a rel="bookmark" href="http://solutionizing.net/2009/04/14/elegant-inline-debug-tracing/">Elegant Inline Debug Tracing</a></li>
<li><a rel="bookmark" href="http://solutionizing.net/2009/03/19/introducing-spweb-getparentweb/">Introducing SPWeb.GetParentWeb()</a></li>
<li><a rel="bookmark" href="http://solutionizing.net/2009/03/19/more-sharepoint-higher-order-functions/">More SharePoint Higher-Order Functions</a></li>
</ul>
<h3>SPExLib Features</h3>
<ul>
<li>Namespace: SPExLib.General
<ul>
<li>Extensions to the .NET 3.5 SP1 Fx</li>
</ul>
</li>
<li>Namespace: SPExLib.SharePoint
<ul>
<li>Extensions to the SharePoint object model.</li>
</ul>
</li>
<li>Namespace: SPExLib.SharePoint.Linq
<ul>
<li>Linq extensions for the SharePoint object model. Including Linq operations on SPWeb/SPSiteCollection using dispose-safe-methods.</li>
</ul>
</li>
<li>Namespace: SPExLib.SharePoint.Linq.Base
<ul>
<li>Implementation of IEnumerable&lt;T&gt; on the SPBaseCollection, which Linq-enables all collections in the SharePoint object model.</li>
</ul>
</li>
<li>Namespace: SPExLib.SharePoint.Security
<ul>
<li>Extension methods that simplifies impersonation tasks on SPSite and SPWeb objects</li>
</ul>
</li>
<li>Namespace: SPExLib.SharePoint.Tools
<ul>
<li>SPDispose checker utilities</li>
</ul>
</li>
<li>Namespace: SPExLib.Diagnostics
<ul>
<li>Debug and Trace features</li>
</ul>
</li>
<li>Namespace: SPExLib.Controls
<ul>
<li>Template classes for WebParts and EditorParts</li>
</ul>
</li>
</ul>
<p><a title="SharePoint Extensions Lib - Release: SPExLib 12.0.0.0" href="http://spexlib.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=28038">Check it out!</a></p>
<br /> Tagged: SPExLib <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/solutionizing.wordpress.com/532/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/solutionizing.wordpress.com/532/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/solutionizing.wordpress.com/532/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/solutionizing.wordpress.com/532/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/solutionizing.wordpress.com/532/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/solutionizing.wordpress.com/532/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/solutionizing.wordpress.com/532/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/solutionizing.wordpress.com/532/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/solutionizing.wordpress.com/532/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/solutionizing.wordpress.com/532/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/solutionizing.wordpress.com/532/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/solutionizing.wordpress.com/532/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/solutionizing.wordpress.com/532/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/solutionizing.wordpress.com/532/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=solutionizing.net&amp;blog=3982353&amp;post=532&amp;subd=solutionizing&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://solutionizing.net/2009/06/01/spexlib-release-these-are-a-few-of-my-favorite-things/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/26483382e3717e58e4c45d06c8ec351d?s=96&#38;d=identicon&#38;r=PG" medium="image">
			<media:title type="html">dahlbyk</media:title>
		</media:content>
	</item>
		<item>
		<title>Workflow at Iowa SharePoint User Group</title>
		<link>http://solutionizing.net/2009/06/01/workflow-at-iowa-sharepoint-user-group/</link>
		<comments>http://solutionizing.net/2009/06/01/workflow-at-iowa-sharepoint-user-group/#comments</comments>
		<pubDate>Mon, 01 Jun 2009 06:37:10 +0000</pubDate>
		<dc:creator>Keith Dahlby</dc:creator>
				<category><![CDATA[Community]]></category>
		<category><![CDATA[IASPUG]]></category>

		<guid isPermaLink="false">http://solutionizing.net/?p=528</guid>
		<description><![CDATA[I will be presenting at the next Iowa SharePoint User Group meeting on Wednesday, June 3: Business Process / Workflow / Forms This month is a two-part session, focusing on business processes, workflows, and forms in SharePoint.  The meeting will cover: Workflow basics Out of the box workflow templates Configuring / customizing workflows Options for building [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=solutionizing.net&amp;blog=3982353&amp;post=528&amp;subd=solutionizing&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>I will be presenting at the next <a href="http://www.sharepointia.com/">Iowa SharePoint User Group</a> meeting on Wednesday, June 3:</p>
<blockquote>
<h4>Business Process / Workflow / Forms</h4>
<p>This month is a two-part session, focusing on business processes, workflows, and forms in SharePoint.  The meeting will cover:</p>
<ul>
<li>Workflow basics</li>
<li>Out of the box workflow templates</li>
<li>Configuring / customizing workflows</li>
<li>Options for building workflows</li>
<li>Building workflows with SharePoint Designer</li>
</ul>
</blockquote>
<blockquote><p><strong>Immediately following the User Group, please join us for a Lunch and Learn with Valeri Topel of KnowledgeLake.</strong> Continuing on the same theme, Valeri will have a presentation and demos showcasing how you can leverage SharePoint for content management business solutions.  Realize a faster ROI and a lower cost of ownership using the platform-based Enterprise Content Management in SharePoint with the KnowledgeLake Document Imaging and Capture system.  Easily manage millions of paper documents, emails, reports and more. Streamline document processing and increase your workers&#8217; efficiency.</p></blockquote>
<blockquote><p>Lunch will be provided.</p></blockquote>
<p><a title="SharePoint and Social Networking Event Details" rel="#someid3" href="http://www.sharepointia.com/Lists/Events%20Calendar/DispForm.aspx?ID=16">Details</a>:</p>
<ul>
<li><strong>When:</strong> Wednesday, June 3, 2009<br />
Registration: 8:30–9:00 AM<br />
Event: 9:00–11:00 AM<br />
Networking/Q&amp;A: 11:00–11:30 AM<br />
Lunch &amp; Learn: 11:30 AM–1:00 PM</li>
<li><strong>Where:</strong> DMACC Ankeny Campus, 2006  South Ankeny Blvd, Ankeny, Iowa 50023 (<a title="Map to DMACC Ankeny Campus" rel="#someid4" href="http://www.dmacc.edu/MapDirectionsAnkeny.asp">map</a>)<br />
Building 24, Health Sciences Building (<a title="Map of DMACC Ankeny Campus" href="http://www.dmacc.edu/share/maps/ankeny.asp">map</a>); Room 216 (<a title="Map of Bldg 24, Second Floor (PDF)" href="http://www.dmacc.edu/share/maps/CampusMapInfo/Ankeny%20Bldg_24%202nd%20Floor.pdf">map</a>)</li>
<li><strong>RSVP:</strong> <a href="https://www.clicktoattend.com/invitation.aspx?code=138602">https://www.clicktoattend.com/invitation.aspx?code=138602 </a></li>
</ul>
<p>If you have ideas or requests for future IASPUG topics, or if you have a topic you would like to present, please send them to <a href="mailto:info@sharepointia.com">info@sharepointia.com</a>.</p>
<br /> Tagged: IASPUG <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/solutionizing.wordpress.com/528/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/solutionizing.wordpress.com/528/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/solutionizing.wordpress.com/528/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/solutionizing.wordpress.com/528/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/solutionizing.wordpress.com/528/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/solutionizing.wordpress.com/528/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/solutionizing.wordpress.com/528/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/solutionizing.wordpress.com/528/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/solutionizing.wordpress.com/528/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/solutionizing.wordpress.com/528/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/solutionizing.wordpress.com/528/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/solutionizing.wordpress.com/528/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/solutionizing.wordpress.com/528/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/solutionizing.wordpress.com/528/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=solutionizing.net&amp;blog=3982353&amp;post=528&amp;subd=solutionizing&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://solutionizing.net/2009/06/01/workflow-at-iowa-sharepoint-user-group/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/26483382e3717e58e4c45d06c8ec351d?s=96&#38;d=identicon&#38;r=PG" medium="image">
			<media:title type="html">dahlbyk</media:title>
		</media:content>
	</item>
		<item>
		<title>SPWebConfigModification Works Fine</title>
		<link>http://solutionizing.net/2009/05/26/spwebconfigmodification-works-fine/</link>
		<comments>http://solutionizing.net/2009/05/26/spwebconfigmodification-works-fine/#comments</comments>
		<pubDate>Tue, 26 May 2009 16:02:43 +0000</pubDate>
		<dc:creator>Keith Dahlby</dc:creator>
				<category><![CDATA[Object Model]]></category>
		<category><![CDATA[SharePoint]]></category>
		<category><![CDATA[SPWebConfigModification]]></category>

		<guid isPermaLink="false">http://solutionizing.net/?p=523</guid>
		<description><![CDATA[Manpreet Alag&#8216;s recent post, SPWebConfigModification does not work on Farms with multiple WFEs, has been making its rounds on Twitter and the link blogs. A post title like that is sure to get attention, but is it really true? After looking a bit closer, I don&#8217;t believe it is. The post suggests that this doesn&#8217;t [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=solutionizing.net&amp;blog=3982353&amp;post=523&amp;subd=solutionizing&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><a href="http://blogs.msdn.com/malag/">Manpreet Alag</a>&#8216;s recent post, <a href="http://blogs.msdn.com/malag/archive/2009/05/22/spwebconfigmodification-does-not-work-on-farms-with-multiple-wfes.aspx">SPWebConfigModification does not work on Farms with multiple WFEs</a>, has been making its rounds on Twitter and the link blogs. A post title like that is sure to get attention, but is it really true? After looking a bit closer, I don&#8217;t believe it is.</p>
<p>The post suggests that this doesn&#8217;t work:</p>
<pre>SPSite siteCollection = new SPSite("http://MOSSServer/");
SPWebApplication webApp = siteCollection.WebApplication;
// ...
webApp.WebConfigModifications.Add(modification);
webApp.Farm.Services.GetValue&lt;SPWebService&gt;().ApplyWebConfigModifications();</pre>
<p>But this does:</p>
<pre>SPWebService.ContentService.WebConfigModifications.Add(modification);
SPWebService.ContentService.Update();
SPWebService.ContentService.ApplyWebConfigModifications();</pre>
<p>Drawing this final conclusion:</p>
<blockquote><p>Instead of adding modifications to <a href="http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.administration.spwebapplication.webconfigmodifications.aspx" target="_blank">WebConfigModifcations</a> of <a href="http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.administration.spwebapplication.aspx" target="_blank">SPWebApplication</a> object, we are using SPWebService.ContentService to call <strong>ADD</strong> and <strong>UPDATE</strong> methods. Whenever required, it is always advised to use <a href="http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.administration.spwebservice.contentservice.aspx" target="_blank">SPWebService.ContentService</a> to make the modifications rather than accessing <a href="http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.administration.sppersistedobject.farm.aspx" target="_blank">Farm</a> instance through <a href="http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.administration.spwebapplication.aspx" target="_blank">SPWebApplication</a>.</p></blockquote>
<p>The suggestion is that there&#8217;s a problem with applying the changes through <code>webApp.Farm</code>. But that <code>Farm</code> is just <code>SPFarm.Local</code>:</p>
<pre>public SPSite(string requestUrl) : this(<strong>SPFarm.Local</strong>, new Uri(requestUrl), false, SPSecurity.UserToken)
{
}</pre>
<p>So the last line is essentially equivalent to this:</p>
<pre>SPFarm.Local.Services.GetValue&lt;SPWebService&gt;()</pre>
<p>Taking a peek at <code>ContentService</code>, we find this definition:</p>
<pre>public static SPWebService get_ContentService
{
    if (SPFarm.Local != null)
    {
        return SPFarm.Local.Services.GetValue&lt;SPWebService&gt;();
    }
    return null;
}</pre>
<p>The modified sample isn&#8217;t actually doing anything different to apply the changes! So the problem is either in how SharePoint handles Web Application-scoped web config changes, or that the changes aren&#8217;t being applied correctly. The latter is much more likely than the former, and indeed the solution is actually quite simple: just look for the only other significant difference between the code samples.</p>
<pre>webApp.WebConfigModifications.Add(modification);
<strong>webApp.Update();</strong> // Oops!
webApp.Farm.Services.GetValue&lt;SPWebService&gt;().ApplyWebConfigModifications();</pre>
<p>A quick PowerShell session or console app would have verified that the config changes weren&#8217;t being saved to the database.</p>
<p>So what have we learned?</p>
<ol>
<li>Always call Update() after making changes to an SPPersistedObject (like SPWebApplication or SPWebService).</li>
<li>SPWebService.ContentService is a shortcut for SPFarm.Local.Services.GetValue&lt;SPWebService&gt;.</li>
<li>Check your code carefully before blaming the SharePoint API!</li>
</ol>
<br /> Tagged: SPWebConfigModification <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/solutionizing.wordpress.com/523/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/solutionizing.wordpress.com/523/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/solutionizing.wordpress.com/523/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/solutionizing.wordpress.com/523/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/solutionizing.wordpress.com/523/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/solutionizing.wordpress.com/523/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/solutionizing.wordpress.com/523/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/solutionizing.wordpress.com/523/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/solutionizing.wordpress.com/523/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/solutionizing.wordpress.com/523/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/solutionizing.wordpress.com/523/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/solutionizing.wordpress.com/523/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/solutionizing.wordpress.com/523/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/solutionizing.wordpress.com/523/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=solutionizing.net&amp;blog=3982353&amp;post=523&amp;subd=solutionizing&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://solutionizing.net/2009/05/26/spwebconfigmodification-works-fine/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/26483382e3717e58e4c45d06c8ec351d?s=96&#38;d=identicon&#38;r=PG" medium="image">
			<media:title type="html">dahlbyk</media:title>
		</media:content>
	</item>
		<item>
		<title>Join SharePoint Lists with LINQ</title>
		<link>http://solutionizing.net/2009/04/30/join-sharepoint-lists-with-linq/</link>
		<comments>http://solutionizing.net/2009/04/30/join-sharepoint-lists-with-linq/#comments</comments>
		<pubDate>Fri, 01 May 2009 04:54:13 +0000</pubDate>
		<dc:creator>Keith Dahlby</dc:creator>
				<category><![CDATA[Object Model]]></category>
		<category><![CDATA[SharePoint]]></category>
		<category><![CDATA[LINQ Join]]></category>
		<category><![CDATA[LINQ SelectMany]]></category>
		<category><![CDATA[SPFieldLookupValue]]></category>

		<guid isPermaLink="false">http://solutionizing.net/?p=509</guid>
		<description><![CDATA[I just read yet another post by Adam Buenz that got me thinking, this time about querying multiple SharePoint lists. Here&#8217;s the code he came up with: var resultSet = list1.Items.Cast&#60;SPListItem&#62;() .Where(i =&#62; Equals (String.Compare(i["Property To Match #1"].ToString(), "Example String Literal"), 0)) .SelectMany(x =&#62; list2.Items.Cast&#60;SPListItem&#62;() .Where(i =&#62; Equals(String.Compare(new SPFieldLookupValue(x["Client"].ToString()).LookupValue, (string) i["Property To Match #2"]), 0))); [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=solutionizing.net&amp;blog=3982353&amp;post=509&amp;subd=solutionizing&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>I just read yet another post by Adam Buenz that got me thinking, this time about <a title="Multiple SPListItemCollection Query With SPFieldLookupValue" href="http://www.sharepointsecurity.com/blog/sharepoint/multiple-splistitemcollection-query-with-spfieldlookupvalue/">querying multiple SharePoint lists</a>. Here&#8217;s the code he came up with:</p>
<pre>var resultSet  = list1.Items.Cast&lt;SPListItem&gt;()
.Where(i =&gt; Equals (String.Compare(i["Property To Match #1"].ToString(), "Example String Literal"), 0))
.SelectMany(x =&gt; list2.Items.Cast&lt;SPListItem&gt;()
    .Where(i =&gt; Equals(String.Compare(new SPFieldLookupValue(x["Client"].ToString()).LookupValue, (string) i["Property To Match #2"]), 0)));</pre>
<p>My first thought was that we could make it more readable with LINQ syntax:</p>
<pre>var res = from SPListItem pi in list1.Items
          where pi["Property To Match #1"] as string == "Example String Literal"
          from SPListItem ci in list2.Items
          where new SPFieldLookupValue(ci["Client"] as string).LookupValue == pi["Property To Match #2"]
          select new { Parent = pi, Child = ci };</pre>
<p>Behind the scenes, this will translate into equivalent extension method calls. The other adjustments are based on personal preference: <code>ToString()</code> can cause <code>null</code> reference exceptions, <code>as string</code> will not; and <a title="BCL Team Blog : String.Compare() != String.Equals() [Josh Free]" href="http://blogs.msdn.com/bclteam/archive/2007/05/31/string-compare-string-equals-josh-free.aspx"><code>String.Compare() != String.Equals()</code></a>.</p>
<p>Next, let&#8217;s optimize the actual SharePoint queries. As a general rule we should always specify the desired <code>ViewFields</code> to eliminate unused data, and our first <code>where</code> clause should be handled with CAML if possible [see also, <a title="Permanent Link to Is it a good idea to use lambda expressions for querying SharePoint data?" rel="bookmark" href="http://blog.mastykarz.nl/lambda-expressions-querying-sharepoint-data/">Is it a good idea to use lambda expressions for querying SharePoint data?</a>].</p>
<pre>var pItems = list1.GetItems(new SPQuery() {
    Query = "... ['Property To Match #1'] == 'Example String Literal'...",
    ViewFields = "..."
});
var cItems = list2.GetItems(new SPQuery() {
    ViewFields = "..."
});
var res = from SPListItem pi in pItems
          from SPListItem ci in cItems
          where new SPFieldLookupValue(ci["Client"] as string).LookupValue == pi["Property To Match #2"]
          select new { Parent = pi, Child = ci };</pre>
<p>Now that we&#8217;re getting our data as efficiently as possible, we can look at what LINQ is doing with them. Behind the scenes, <code>SelectMany</code> is essentially implemented like this:</p>
<pre>public static IEnumerable&lt;TResult&gt; SelectMany&lt;TSource, TResult&gt;(
    this IEnumerable&lt;TSource&gt; source,
    Func&lt;TSource, IEnumerable&lt;TResult&gt;&gt; selector)
{
    foreach(TSource element in source)
        foreach(TResult childElement in selector(element))
            yield return childElement;
}</pre>
<p>For each item in our parent collection (<code>source</code>), the entire child collection is enumerated in search of items that match the predicate. This seems rather inefficient since we&#8217;re comparing the same values each time. Conveniently, LINQ provides a <code>join</code> operator for this purpose:</p>
<pre>var res = from SPListItem pi in pItems
          join SPListItem ci in cItems
              on pi["Property To Match #2"]
              equals new SPFieldLookupValue(ci["Client"] as string).LookupValue
          select new { Parent = pi, Child = ci };</pre>
<p>Behind the scenes, this translates into a call to the Join method:</p>
<pre>var res = pItems.Cast&lt;SPListItem&gt;().Join(cItems.Cast&lt;SPListItem&gt;(),
              pi =&gt; pi["Property To Match #2"],
              ci =&gt; new SPFieldLookupValue(ci["Client"] as string).LookupValue,
              (pi, ci) =&gt; new { Parent = pi, Child = ci }
          );</pre>
<p>Note that the left- and right-hand sides of the <code>equals</code> keyword are treated separately. The left-hand side operates on the first collection, the right-hand side operates on the second collection, and obviously both expressions must return the same type. This might be easier to see from an implementation of <code>Join</code>:</p>
<pre>public static IEnumerable&lt;TResult&gt; Join&lt;TOuter, TInner, TKey, TResult&gt;(
    this IEnumerable&lt;TOuter&gt; outer,
    IEnumerable&lt;TInner&gt; inner,
    Func&lt;TOuter, TKey&gt; outerKeySelector,
    Func&lt;TInner, TKey&gt; innerKeySelector,
    Func&lt;TOuter, TInner, TResult&gt; resultSelector)
{
    ILookup&lt;TKey, TInner&gt; lookup = inner.ToLookup(innerKeySelector);
    return from outerItem in outer
           from innerItem in lookup[outerKeySelector(outerItem)]
           select resultSelector(outerItem, innerItem);
}</pre>
<p>So in our case, <code>Join</code> will build a lookup of all child items based on the lookup value, and then perform a <code>SelectMany</code> to cross join the parent items with the child items found from a lookup by the matched property. This dictionary lookup will almost certainly perform better than a full enumeration of the list, especially for larger lists and more complex keys.</p>
<br /> Tagged: LINQ Join, LINQ SelectMany, SPFieldLookupValue <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/solutionizing.wordpress.com/509/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/solutionizing.wordpress.com/509/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/solutionizing.wordpress.com/509/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/solutionizing.wordpress.com/509/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/solutionizing.wordpress.com/509/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/solutionizing.wordpress.com/509/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/solutionizing.wordpress.com/509/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/solutionizing.wordpress.com/509/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/solutionizing.wordpress.com/509/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/solutionizing.wordpress.com/509/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/solutionizing.wordpress.com/509/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/solutionizing.wordpress.com/509/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/solutionizing.wordpress.com/509/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/solutionizing.wordpress.com/509/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=solutionizing.net&amp;blog=3982353&amp;post=509&amp;subd=solutionizing&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://solutionizing.net/2009/04/30/join-sharepoint-lists-with-linq/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/26483382e3717e58e4c45d06c8ec351d?s=96&#38;d=identicon&#38;r=PG" medium="image">
			<media:title type="html">dahlbyk</media:title>
		</media:content>
	</item>
		<item>
		<title>Elegant Inline Debug Tracing</title>
		<link>http://solutionizing.net/2009/04/14/elegant-inline-debug-tracing/</link>
		<comments>http://solutionizing.net/2009/04/14/elegant-inline-debug-tracing/#comments</comments>
		<pubDate>Wed, 15 Apr 2009 04:37:33 +0000</pubDate>
		<dc:creator>Keith Dahlby</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[F#]]></category>
		<category><![CDATA[Object Model]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[SharePoint]]></category>
		<category><![CDATA[Debugging]]></category>
		<category><![CDATA[higher-order function]]></category>

		<guid isPermaLink="false">http://solutionizing.net/?p=500</guid>
		<description><![CDATA[As much fun as it is to step through code with a debugger, I usually prefer to use System.Diagnostics.Debug and Trace with DebugView to see what&#8217;s happening in realtime. This is particularly handy to track intermediate results in higher-order functions that you might not be able to step into. However, it&#8217;s not always convenient to [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=solutionizing.net&amp;blog=3982353&amp;post=500&amp;subd=solutionizing&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>As much fun as it is to step through code with a debugger, I usually prefer to use <a title="Debug Class (System.Diagnostics)" href="http://msdn.microsoft.com/en-us/library/system.diagnostics.debug.aspx"><code>System.Diagnostics.Debug</code></a> and <a title="Trace Class (System.Diagnostics)" href="http://msdn.microsoft.com/en-us/library/system.diagnostics.trace.aspx"><code>Trace</code></a> with <a title="DebugView for Windows" href="http://technet.microsoft.com/en-us/sysinternals/bb896647.aspx">DebugView</a> to see what&#8217;s happening in realtime. This is particularly handy to track intermediate results in higher-order functions that you might not be able to step into. However, it&#8217;s not always convenient to insert debugging statements amongst the composed expressions of F#, PowerShell or LINQ.</p>
<p>An alternative first came to mind while working in F#:</p>
<pre>let dbg x = System.Diagnostics.Debug.WriteLine(x |&gt; sprintf "%A"); x</pre>
<p>(Read <code>|&gt;</code> as &#8220;as next parameter to&#8221;.) We can then use this function anywhere to peek at a value, perhaps an intermediate list in this trivial example:</p>
<pre>let data = [1..10]
           |&gt; List.filter (fun i -&gt; i%3 = 0) |&gt; dbg
           |&gt; List.map (fun i -&gt; i*i)</pre>
<p>Indeed <code>[3; 6; 9]</code> are traced as multiples of three. Not a particularly convincing example, but it should be pretty easy to imagine a more complex algorithm for which unintrusive tracing would be useful.</p>
<p>This works pretty well with F#&#8217;s <code>|&gt;</code> operator to push values forward, but what about C#? Given my posting history, it shouldn&#8217;t be hard to guess where I&#8217;m going with this&#8230;</p>
<h3>Extension Methods</h3>
<p>So if <code>|&gt;</code> is &#8220;as next parameter to&#8221;, the <code>.</code> of an extension method call might read &#8220;as first parameter to&#8221;. So we can implement a roughly equivalent function (sans F#&#8217;s nice deep-print formatter <code>"%A"</code>) like so:</p>
<pre>    public static T Debug&lt;T&gt;(this T value)
    {
        Debug.WriteLine(value);
        return value;
    }

    public static T Dbg&lt;T&gt;(this T value, string category)
    {
        Debug.WriteLine(value, category);
        return value;
    }</pre>
<p><del datetime="2009-04-19T20:15:33+00:00">I find the optional label handy to keep different traces separate.</del> <ins datetime="2009-04-19T20:15:33+00:00">Looking again, there&#8217;s an overload that accepts a category, so we&#8217;ll use that instead.</ins> So why might this be useful? Maybe we want to log the value assigned within an object initializer:</p>
<pre>var q = new SPQuery() {
  Query = GetMyQuery().Debug("Query")
};</pre>
<p>Rather than store the query string to a temporary variable or retrieve the property after it&#8217;s been set, we can just trace the value inline. Or consider a LINQ example:</p>
<pre>var items = from SPListItem item in list.GetItems(q)
            let url = new SPFieldUrlValue(item["URL"] as string)
            where url.Url.Debug("URL").StartsWith(baseUrl, StringComparison.OrdinalIgnoreCase)
            select new
            {
                Title = item.Title.Debug("Title"),
                Description = url.Description,
            };</pre>
<p>Here we log all URLs that pass through, even the ones excluded from the result by the predicate. This would be much harder to implement efficiently without inline logging.</p>
<p>This technique works great for simple objects with a useful <code>ToString()</code>, but what about more complex objects? As has often been the answer lately, we can use higher-order functions:</p>
<pre>    public static T Dbg&lt;T, R&gt;(this T value, Func&lt;T, R&gt; selector)
    {
        Debug.WriteLine(selector(value));
        return value;
    }

    public static T Dbg&lt;T, R&gt;(this T value, string category, Func&lt;T, R&gt; selector)
    {
        Debug.WriteLine(selector(value), category);
        return value;
    }</pre>
<p>Now we can provide a delegate to trace whatever we want without affecting the object itself. For example, we can easily trace a row count for the <code>DataView</code> being returned:</p>
<pre>public DataView GetResults()
{
    var myTable = GetDataTable();
    // Process data...
    return myTable.DefaultView.Dbg("Result Count", v =&gt; v.Count);
}</pre>
<p>I could go on, but you get the idea.</p>
<h3>PowerShell Filter</h3>
<p>Finally, we can implement similar functionality in PowerShell using a filter with an optional scriptblock parameter:</p>
<pre>filter Debug([scriptblock] $sb = { $_ })
{
  [Diagnostics.Debug]::WriteLine((&amp; $sb))
  $_
}

PS &gt; 1..3 | Debug { $_*2 } | %{ $_*$_ }
1
4
9</pre>
<p>Which traces 2, 4, 6, as expected.</p>
<p><strong>Update 4/19/2009:</strong> Changed functions to use category overloads. And another point to consider: if the value being traced could be <code>null</code>, <code>selector</code> should be designed accordingly to avoid <code>NullReferenceException</code>. There&#8217;s nothing worse than bugs introduced by tracing or logging.</p>
<br /> Tagged: Debugging, higher-order function <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/solutionizing.wordpress.com/500/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/solutionizing.wordpress.com/500/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/solutionizing.wordpress.com/500/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/solutionizing.wordpress.com/500/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/solutionizing.wordpress.com/500/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/solutionizing.wordpress.com/500/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/solutionizing.wordpress.com/500/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/solutionizing.wordpress.com/500/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/solutionizing.wordpress.com/500/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/solutionizing.wordpress.com/500/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/solutionizing.wordpress.com/500/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/solutionizing.wordpress.com/500/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/solutionizing.wordpress.com/500/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/solutionizing.wordpress.com/500/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=solutionizing.net&amp;blog=3982353&amp;post=500&amp;subd=solutionizing&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://solutionizing.net/2009/04/14/elegant-inline-debug-tracing/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/26483382e3717e58e4c45d06c8ec351d?s=96&#38;d=identicon&#38;r=PG" medium="image">
			<media:title type="html">dahlbyk</media:title>
		</media:content>
	</item>
	</channel>
</rss>
