Keyboard Shortcuts of the Trade

I’ve always been a huge fan of keyboard shortcuts, they save you time after all, so who wouldn’t be a fan?  Given the universe of keyboard shortcuts available in Visual Studio 2010, I’m always interested in seeing which ones fellow colleagues use versus what I use, as it never hurts to increase your productivity.  With that being said, this first part of this post is dedicated to calling out my basic arsenal of shortcuts for this software package.  Should any of my readers have some additions they deem absolutely life-saving, call them out!

Ctrl K, Ctrl K		Toggle bookmark
Ctrl K, Ctrl N		Next bookmark
F5					Run (typically used for simple applications)
Ctrl F5				Run and keep window open (applies to console applications only)
F9					Toggle breakpoint on and off
F10					Step next (Debugging)
F11					Step into (Debugging)
Ctrl M, Ctrl O		Collapse outlines
Ctrl -				Step back a location
Ctrl Shift -		Step forward a location
F12					Go to definition
Shift F12			Find code references (use full text search for finding client-side references)
Ctrl Shift B		Full build

All too often I find myself jumping between one body of code and another (and potentially a third or fourth!).  This is why I place so much value on the bookmark shortcuts, particularly since they can be used across both markup and implementation files. 

Another shortcut worth highlighting is the collapse outlines shortcut.  When working with a meaty project and trying to navigate around, I find it very useful to be able to quickly collapse everything to get a bird’s eye view over all that’s going on in a particular file.  This can sometimes be misleading though when there are numerous nested regions at play, but for the most part, very useful shortcut!

Stepping back and forward locations is hugely useful when you are diving deep into a particular stack trace or perhaps f12′ing very deep into a body of code and you need to work your way back to where you began.  Living without this shortcut is akin to living without a back button in a web browser.

Tools of the Trade

Now we get to the topic of super useful developer tools.  This list could be super long, but I’ve widdled it down to the list of what I’d install right out the gate if working with a fresh OS install.

ILSpy
This tool is very similar to another more well-known one called Reflector, used for inspecing assembly packages (that aren’t obfuscated).  The only major difference is Reflector went to a paid version only I believe, at which point a colleague stumbled upon this one, which is free.

Fiddler
If you do any serious amount of web development, you absolutely can’t live without this tool.  It is basically a packet sniffer for web requests and responses.  Given the “chatty” nature of the web these days with everything funneling through silent AJAX calls and such, it is extremely useful to have this detailed view of the individual HTTP GET’s and POST’s to be able to troubleshoot issues, both at the server level as well as the client level (JSON and the likes).

DebugView
This tool is great for debugging.  It allows you to hook onto the machine’s trace stream per se.  So if you’ve got an application you’ve just thrown down some trace statements in and you execute it, this little tool will spam all your trace statements into its GUI.  Think of it as an addition to typical logging, such as Log4Net

Firebug
Rich jQuery work these days wouldn’t be the same without this one tool.  With the advent of dynamic DOM’s, thanks to the robustnes of the jQuery libraries, this tool enables you to see DOM changes live as they take place based on whatever client-side events occur.  Without this tool, you’re essentially flying blind, although to be fair, we now have fairly competitive choices with the latest Chrome and IE browsers, but for quite a while there weren’t other options.

Notepad++
This is more of a personal preference, but I love this tool if for no other reason than it supports opening virtually anything and has some very handy utilities for auto-formatting commonly mal-formatted file types such as HTML and XML.

Beyond Compare
When dealing with code comparisons, or in particular, code merging conflict resolution, this tool is extremely valuable and hooks into TortoiseSVN perfectly.

TortoiseSVN
This little tool hooks into the windows shell to allow you to leverage Subversion using a graphical GUI without having to go old-school on it via command line.  If you use SVN (which is excellent) for code management, you can’t live without this add-on.

LINQPad
This tool is very handy if you need to throw some LINQ directly at a particular database without going through your typical application layer.  Be sure if you use this tool to pay for the upgrade, as the intellisense integration is definitely a life-saver and worth it.

What
Say you’ve got a SharePoint site up and running and you need to provide a hook for some custom programming logic that only occurs when certain events are triggered from SharePoint. Some examples of the most basic events would be when a user on the site adds, updates, or deletes an SPListItem (either through the OOB GUI or some custom implementation). Thinking about events in SharePoint is akin to thinking about events in C# (Click, Hover, ItemDataBound, etc…) for example. A user performs an action, and some block of code executes when that something is done (or possibly before that something is done).

Why
As was alluded to above, often times there are needs to run a block of code after (or during) an event in SharePoint. Such examples could be cleanup jobs, or potentially database-level data synchronization needs, it all boils down to the project needs.  Bottom line is most projects are predominately event-driven, so event receivers are a core part of your toolkit when integrating SharePoint into a project solution.

How
I’ll start with a birds-eye view before diving into some detailed code examples. If you want SharePoint to leverage Event Receivers, one way to do so is by authoring your own custom assembly that you strong-name and GAC. Afterwards, all that is necessary is to subscribe (a.k.a.  register if you prefer) SharePoint to the specific events within the GAC’d assembly (more on that in a moment).

Before we get into the examples of how to subscribe/unsubscribe SharePoint to particular event receivers in your GAC’d assembly, I’ll first touch on the basic structure of how to author your Event Receiver assembly.

public class CustomEventReceiver : SPItemEventReceiver
{
	/// <summary>
	/// Default constructor
	/// </summary>
	public CustomEventReceiver()
	{
	}

	/// <summary>
	/// Event raised by SharePoint after item has finished adding.
	/// </summary>
	public override void ItemAdded(SPItemEventProperties properties)
	{
		try
		{
			base.ItemAdded(properties);

			//...
		}
		catch (Exception e)
		{
			properties.ErrorMessage = "An error occurred during your request. (IA)";
			properties.Cancel = true;
		}
	}

	/// <summary>
	/// Event raised by SharePoint after item has finished updating.
	/// </summary>
	public override void ItemUpdated(SPItemEventProperties properties)
	{
		try
		{
			base.ItemUpdated(properties);

			//...
		}
		catch (Exception e)
		{
			properties.ErrorMessage = "An error occurred during your request. (IU)";
			properties.Cancel = true;
		}
	}

	/// <summary>
	/// Event raised by SharePoint after item has finished deleting.
	/// </summary>
	public override void ItemDeleted(SPItemEventProperties properties)
	{
		try
		{
			base.ItemDeleted(properties);

			//...
		}
		catch (Exception e)
		{
			properties.ErrorMessage = "An error occurred during your request. (ID)";
			properties.Cancel = true;
		}
	}
}

The above code shows that we create a custom class inheriting from the SPItemEventReceiver class (Microsoft.SharePoint namespace FYI), declare the default constructor, and declare 3 basic event receiver methods as defined in our parent class.  All accessible data pertaining to a particular event lives within the inbound properties to the method.  You’ll find as you explore the various lifecycles of events (ItemAdding versus ItemAdded) as well as matching stages across events (ItemAdded versus ItemDeleted), the inbound data that is made available to you is very inconsistent, so be aware that you’ll likely run into a lot of unexpected null’s through trial and error (pretty painful at times but unavoidable in this part of the SharePoint world).

Now that you’ve seen the basics on how to set up Event Receiver layers, the only major pieces of business left to deal with are the register/unregister blocks.  I personally find it simplest to have a utility command line tool that you make use of for leveraging your code.

public class CommandLine
{
	/// <summary>
	/// The main driver method for the console application
	/// </summary>
	public static void Main(string[] args)
	{
		try
		{
			//Establishing which eventReceiverTypes we want to support
			supportedEventReceiverTypes.Add(SPEventReceiverType.ItemAdded);
			supportedEventReceiverTypes.Add(SPEventReceiverType.ItemDeleted);
			supportedEventReceiverTypes.Add(SPEventReceiverType.ItemUpdated);

			//Registering all of our SPList's to all of our supported event receiver types
			foreach (string e in Enum.GetNames(typeof(SPListName)))
				RegisterEventReceivers(web, assembly, className, supportedEventReceiverTypes, e);

			//Unregistering all of our SPList's from all of our supported event receiver types
			foreach (string e in Enum.GetNames(typeof(SPListName)))
				UnregisterEventReceivers(web, assembly, supportedEventReceiverTypes, e);
		}
		catch (Exception e)
		{
			Console.WriteLine("Error: {0}", e.ToString());
		}
	}

	/// <summary>
	/// This method will register all supported eventReceiverTypes for a specified SharePoint list
	/// </summary>
	private static bool RegisterEventReceivers(SPWeb web, string assembly, string className, List<SPEventReceiverType> eventReceiverTypes, string listName)
	{
		try
		{
			foreach (SPEventReceiverType eventReceiverType in eventReceiverTypes)
			{
				SPEventReceiverDefinition def = web.Lists[listName].EventReceivers.Add();
				def.Name = eventReceiverType.ToString();
				def.Synchronization = SPEventReceiverSynchronization.Synchronous;
				def.Type = eventReceiverType;
				def.Assembly = assembly;
				def.Class = className;
				def.Update();
			}

			web.Lists[listName].Update();
			return true;
		}
		catch (Exception e)
		{
			Console.WriteLine("Error: {0}", e.ToString());
			return false;
		}
	}

	/// <summary>
	/// This method will unregister all supported eventReceiverTypes for a specified SharePoint list
	/// </summary>
	private static bool UnregisterEventReceivers(SPWeb web, string assembly, List<SPEventReceiverType> eventReceiverTypes, string listName)
	{
		try
		{
			List<SPEventReceiverDefinition> definitionsToDelete = new List<SPEventReceiverDefinition>();

			foreach (SPEventReceiverDefinition receiverDef in web.Lists[listName].EventReceivers)
				if (receiverDef.Assembly == assembly && eventReceiverTypes.Contains(receiverDef.Type))
					definitionsToDelete.Add(receiverDef);

			for (int count = 0; count < definitionsToDelete.Count; count++)
				definitionsToDelete[count].Delete();

			return true;
		}
		catch (Exception e)
		{
			Console.WriteLine("Error: {0}", e.ToString());
			return false;
		}
	}

	private static List<SPEventReceiverType> supportedEventReceiverTypes = new List<SPEventReceiverType>();
	private static string assembly = ConfigurationManager.AppSettings["Assembly"];
	private static string className = ConfigurationManager.AppSettings["ClassName"];
	private enum SPListName
    {
        ListName1,
		ListName2,
		ListName3
    }
}

As can be seen above, there is a main driver method that declares which events we care about, then it simply subscribes each SPList to all of the events, followed by unsubscribing each SPList from all of the events (for the sake of providing both examples of course).

One thing to note here is that I intentionally declare the SPEventReceiverDefinitions in this fashion (there are other shorter ways) so that you have the ability to specify “Synchronous” (the default behavior is asynchronous).  Now because these are synchronous, you’ll notice back in our assembly logic up top, we set the properties.ErrorMessage and properties.Cancel properties accordingly.  These help control the synchronous flow of the web request by the triggering user.  So if something fails in the event receiver layer, the code is smart enough to signal back to the calling web tier that a problem occurred.  If the event receivers had been set up asynchronously, then the ErrorMessage/Cancel properties would be of lesser use.  Nevertheless, I hope this has been an informative overview / quick start for leveraging Event Receivers with SharePoint 2010, good luck!

P.S. – Since your event receiver assembly is in the GAC, anytime you make a change to the logic and re-GAC it, don’t forget to perform an IIS reset or SharePoint will hold onto the old version of the GAC’d assembly.

I was recently facing a major production performance bottleneck with a SharePoint 2010 site.  After a bit of digging around, I came to the realization that leveraging LINQ to SharePoint (SPMetal) for querying against SPLists with several hundred (yes, not even thousand) items resulted in very poor performance.  I originally thought that the LINQ to SharePoint provider was smart enough to take your LINQ and convert it into CAML queries to issue against SharePoint, much like LINQ to SQL/Entity gets converted into raw SQL to be issued against your DB server.  Much to my dismay, this turned out to be an incorrect assumption and the poor performance was due to LINQ to SharePoint literally performing full scans against the SPLists (looking for SPListItems that met the simple where clause condition) rather than issuing queries against the SharePoint content database directly.

I had never worked directly with CAML queries before (somehow had managed to dodge that bullet all this time) but they’re honestly not that bad, once you get over a few hurdles that can burn some hours.  A few mistakes to watch out for:

  1. Hand writing CAML queries seems like a great idea until you realize just how picky the syntax is (don’t do it) – use a tool like U2U CAML Query Builder (latest version of tool is for SharePoint 2007 but works with 2010 just fine).
  2. Specifying XML element attributes with single quotes rather than double quotes does not work and is very hard to track down at runtime.
  3. Placing an outer <And> or <Or> element surrounding your query conditions is only a good idea if you actually have multiple conditions to AND or OR.  If you don’t, this too results in misleading errors and hair-pulling.

Having gotten the unfamiliar technology growing pains out of the way, the rest went pretty smoothly.

SPSecurity.RunWithElevatedPrivileges(delegate()
{
	using (SPSite site = new SPSite(SharePointHelper.WebApplicationRoot))
	{
		using (SPWeb web = site.OpenWeb())
		{
			web.AllowUnsafeUpdates = true;

			//Various object instantiations
			List<SPListItem> listItems = new List<SPListItem>();
			SPQuery query = new SPQuery();
			StringBuilder queryXML = new StringBuilder();

			//Generating custom CAML query
			queryXML.Append("<Where>");
			queryXML.Append("<Contains>");
			queryXML.Append("<FieldRef Name=\"Groups\" />");
			queryXML.Append("<Value Type=\"MultiChoice\">" + groupGuid.ToString() + "</Value>");
			queryXML.Append("</Contains>");
			queryXML.Append("</Where>");

			//Assigning custom CAML query to query object
			query.Query = queryXML.ToString();

			//Executing custom CAML query and converting results to list
			listItems = web.Lists[nonGroupICRType.ToString()]
				.GetItems(query)
				.Cast<SPListItem>()
				.ToList();

			//Actions on listItems would continue here...
		}
	}
});

As can be seen above, the CAML query is being crafted inline via a StringBuilder but you could of course refactor this into an external XML file and load it at runtime if you’re dealing with more complex queries.  You’ll notice I’m using the equivalent of a SQL “LIKE” statement with the <Contains> element.  You’ll also notice that I’m issuing this query against a single SPList via SPList.GetItems(…), then casting the resulting collection into something more LINQ-friendly.

For my business need I had 5 such SPLists to issue the same query against so I spent some time exploring the similar SPWeb.GetSiteData(…) call in the hopes of consolidating all 5 calls into 1.  This is a very powerful call that allows you to perform CAML queries across multiple SPLists, SPWebs, etc…The only problem is it results in a DataTable response.  This kind of response is useful enough if all you need to do is read data, but in my case, I needed to literally make changes to every SPListItem that met the CAML query selection condition.  If you stuck to using the SPWeb.GetSiteData(…) call, you’d still need to ask SharePoint for each and every SPListItem via the DataRow guids.  It kind of defeated the purpose, that being to improve performance.  This call definitely has its place when you need to perform some mass read-only querying, but didn’t fit the bill this time, so I turned to issuing the SPList.GetItems(…) call across the 5 lists.

End result was that performance improved dramatically now that the CAML query was being leveraged against each SPList rather than leaning on LINQ to SharePoint to correctly do this.  So if you ever find yourself needing to scan lots of SPListItems efficiently, look no further than CAML queries.