Using SPMetal in SharePoint 2010

One of the best development features in making customisations within a SharePoint environment is the SPMetal tool. The SPMetal tool generates entity classes in order to use LINQ syntax to retrieve items from lists. The SPMetal.exe resides in the 14/bin folder. I will show you a quick demonstration on how I have generated a DataContext class using the SPMetal executable.

You will need to create two files:

  1. XML file – containing the list or library name we are interested in generating our class from. In the code snippet (below), the list I am interested in is called Quicklinks.
<?xml version="1.0" encoding="utf-8"?>
<Web xmlns="http://schemas.microsoft.com/SharePoint/2009/spmetal">
  <List Name="Quicklinks" Member="Quicklinks" />
  <ExcludeOtherLists />
</Web>

Save the XML file into the 14/bin director and name it “SPMetalConfig.xml”.

  1. Batch File – will contain the SharePoint command prompt needed to fire the SPMetal executable. Creating a batch file is not required. You can run the command as normal through Windows Command Line. I just find it a lot easier to manage and make changes using a batch file.
SET SPMETALDIR="C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\BIN\" 

cd %SPMETALDIR% 

spmetal.exe /web:http://myintranet /code:QuicklinksOMEnitites.cs /parameters:SPMetalConfig.xml

Once this has run, a class called “QuicklinksOMEnitites.cs” will be generated in the 14/bin folder.

SPMetal.exe

One thing I did find when using SPMetal for retrieving list data to be output to a custom webpart was that it is only able to retrieve data from a site collection the list resides. But this is probably to be expected. So if the webpart was used in a separate site collection, no data will be shown. In order to get around this, SPMetal will not suffice. You will need to go through the code route and do the following:

SPSecurity.RunWithElevatedPrivileges(delegate()
{
    using (SPWeb intranetSite = new SPSite("http://myintranet/sites/depts/").OpenWeb())
    {
        SPList quickLinks = intranetSite.Lists.TryGetList("Quicklinks");
        
        if (quickLinks != null)
        {
            //Do something with list data.
        }                           
    }
}); 

XmlDocument.Load Error Handling

From one of the projects I have been working on, I came across a snippet of code that used the XmlDocument.Load method. What alarmed me about this piece of code was the fact that there was no error handling. If for some reason the XML file could not be found or a node was missing, the whole page would have crashed. Not good.

I must admit, I am not exactly the best person to speak about implementing wide-scale error handling in every facet of code. But I do ensure the core foundations of an application or website do incorporate sufficient error handling.

So back to the matter in hand. This is the original code using the XmlDocument.Load functionality:

XmlDocument doc = new XmlDocument();

doc.Load(Server.MapPath("/xml/storeGB.xml"));

XmlNode countryNode = doc.SelectSingleNode("//countries");
foreach (XmlNode node in countryNode.ChildNodes)
{
    //Do something with the elements
    Response.Write(node.Name + node.InnerText);
}

I changed the code to the following:

XmlDocument doc = new XmlDocument();

//Check if language XML file exists
if (File.Exists(Server.MapPath("/xml/storeGB.xml")))
{
    try
    {
        doc.Load(Server.MapPath("/xml/storeGB.xml"));

        XmlNode countryNode = doc.SelectSingleNode("//countries");

        if (countryNode != null)
        {
            foreach (XmlNode node in countryNode.ChildNodes)
            {
                //Do something with the elements
                Response.Write(node.Name + node.InnerText);
            }
        }
        else
        {
            //Output error message if there is no node
        }
    }
    catch (XmlException ex)
    {
        Debug.WriteLine(String.Format("XmlException for countries: {0}", ex.Message));
    }
}

I am sure you will agree that this is the better approach to using XmlDocument.Load.

String.Format In JavaScript

Whenever I work with strings whilst programming in .NET, somewhere along the lines I always find myself using the awesome “string.format”. I think all of you will admit its the most useful and easiest way to build up your strings.

The only downside to using the “string.format” method is that it lures you into a false sense of security and you find yourself lost without it when it comes to working with strings in other languages. This happened to me when I had to build up a long string in JavaScript. It was long and tedious…or maybe I am just lazy.

Luckily, there have been a few developers who extended the string object in JavaScript to include “string.format”. Amazing! Its goes along the lines of adding this to your own JavaScript code:

String.format = String.prototype.format = function() {
    var i=0;
    var string = (typeof(this) == “function” && !(i++)) ? arguments[0] : this;

    for (; i < arguments.length; i++)
        string = string.replace(/\{\d+?\}/, arguments[i]);

    return string;
}

Here are some other useful links I have found on how to implement “string.format” into your JavaScript code:

FCKEditor’s Remove Formatting - Block Elements

The “Remove Format” button (Remove Formatting Button) within FCKEditor, only removes valid inline elements such as: strong, span, strike, font, em, etc.

If you want to be able to make the Remove Formatting function more flexible so that it removes block elements, you can do so by modifying the “fckconfig.js” file found within the FCKeditor folder.

Search for the “FCKConfig.RemoveFormatTags” line, which will look something like this:

FCKConfig.RemoveFormatTags = 'b,big,code,del,dfn,em,font,i,ins,kbd,q,samp,small,span,strike,strong,sub,sup,tt,u,var';

All you need to do now is add any additional elements you wish to remove from your content. In my case, I wanted the Remove Formatting button to remove all header tags. So I carried out the following:

FCKConfig.RemoveFormatTags = 'b,big,code,del,dfn,em,font,i,ins,kbd,q,samp,small,span,strike,strong,sub,sup,tt,u,var,h1,h2,h3';

SharePoint Site Architecture – SPSites and SPWebs

I have been developing custom web parts and SharePoint customisations for a couple years now. During the early stages of SharePoint development I found a great deal of confusion when trying to retrieve information from different areas of an intranet through using the SPSite and SPWeb methods.

I think any other developer who is starting out SharePoint development may encounter the same issue. What I found useful was the “Site Architecture and Object Model Overview” diagram from the MSDN site.

SharePoint Site Architecture

It nicely breaks down the architecture of a SharePoint site. I highly recommend that you take look at the following links containing more diagrams:

Whilst I am talking about SPSite’s and SPWebs’s in this post, I’ll give you quick overview on how they work using the (above) diagram. Basically, the top level site collection (SPSite) contains your root web (SPWeb) and subsites (SPWebs under SPWebs). So, a subsite will be any site (SPWeb) under the top level web site in a site collection (SPSite).

Backing up Google Account Data

In light of what has happened recently with some 150,000 Google Account holders loosing their information due to a mishap at Google HQ over the weekend really reinforces the fact that our data is not safe…even in the “cloud”.

At the end of the day our information is stored on hardware that can fail. I think that this whole “cloud computing” malarkey has got all lured into a false sense of security where we think we don’t need to take measures to ensure our data backed up on a regular basis. I have to admit, I too have become a bit tardy when it comes to backing up my online data. If a large company like Google can get it wrong, what hope is there for other companies offering the same thing?

I practically live on the “cloud” in terms of what Google has to offer. I use their email, calendar, document and notebook applications. Even their mobile phone OS: Android! Luckily, there are steps we can take to ensure our data is backed up on your own terms:

Google Calendar Google Calendar

Google Calendar is the one application I use the most. If I lost all my data, I would quite annoyed to say the least (and be very disorganised).

You can backup all your calendar entries by opening your calendar settings, click on Calendars and select “Export Calendars”. A zip file will be created containing your calendars in a .ical format.
 
GmailLogo Gmail

This a simple one. Use an desktop email client such as Thunderbird (or any other client you prefer) to download all your emails directly to you computer through POP access.
 
GoogleDocsLogo Docs

If you only store a handful of documents in your Google Account, you could just download them one-by-one. Understandably, if you have a long list of documents a more automated approach is required.

Lifehacker.com shows a really great script you can use to that allows you to download documents in whatever format you require. Take a look here.
 

Hooray! Our data is saved!

UserProfileManager.Count – Don’t Count On It!

In ASP.NET you would think when you use the “.Count” method that it would be able to simply return the total number of elements within a collection. In majority of cases this is right. Well, apart from when you use the “.Count” method against a collection of profiles within SharePoint. For example:

UserProfileManager profileManager = new UserProfileManager(myContext);

//Get total number of profiles
int numberOfProfiles = profileManager.Count;

I found that I came across two issues when using the code above:

  1. The incorrect number of profiles was returned.
  2. For some reason, when I deployed the code to a live server environment I kept on getting errors from the line where the count was being returned.

From researching this issue on various blog posts and forums, it seems that UserProfileManager.Count does indeed have issues in returning the count correctly. The only way to get around this is to enumerate through the UserProfileManager:

UserProfileManager profileManager = new UserProfileManager(myContext);

int counter = 0;

IEnumerator profileEnumerator = profileManager.GetEnumerator();
while (profileEnumerator.MoveNext())
{
    counter++;
}

//Number of profiles
int totalNumberOfProfiles = counter;

This will give us an accurate number of profiles that are stored within SharePoint and without any silly errors.

Reference Custom CSS and JavaScript files in SharePoint 2010

I have been building a custom .NET web part page to use in my SharePoint intranet. The .NET page has quite a lot of custom HTML and jQuery design elements, so using CSS and JavaScript files were essential.

As you know, when we want to use elements from our CSS and JavaScript files we normally add the following lines of HTML at the top of our page:

<!-- CSS -->
<link type="text/css" rel="stylesheet" href="site.css" />

<!-- JavaScript -->
<script src="jQuery.js" type="text/javascript" />

If you added those lines of code in a custom SharePoint page, you’ll find that the page will ignore them. Thankfully, SharePoint has given us some controls to add these references.

At this point its worth stating that I stored all my required JavaScript and CSS files within the “Style Library” directory situated in the root of any SharePoint 2010 intranet. In order to get these files I used controls called”CssRegistration” and “ScriptLink”:

<!-- CSS -->
<SharePoint:CssRegistration ID="CssRegistration1" Name="/Style Library/Home/CSS/jcarousel.css" runat="server" After="corev4.css" />

<!-- JavaScript -->
<SharePoint:ScriptLink ID="ScriptLink1" Name="~sitecollection/Style Library/Home/JS/jquery-1.4.4.min.js" runat="server" />

If you have stored your CSS and JavaScript within the physical file directory situated in the 14 hive folder, you will need to modify the above example to the following:

<!-- CSS -->
<SharePoint:CSSRegistration Name="<% $SPUrl:~SiteCollection/Style Library/Core Styles/jcarousel.css%>" runat="server"/>

<!-- JavaScript -->
<SharePoint:ScriptLink ID="ScriptLink1" Name="<% $SPUrl:~SiteCollection/Style Library/Core Styles/jquery.js%>" runat="server" />

The only difference between this example and our earlier example is that when we have just added “SPUrl” to get files relative to the current site collection.

Retrieve and Manage User Profile Properties in SharePoint 2010

I am writing a custom webpart that will output user profile information from SharePoint 2010. My code requires me to get quite a few fields. Most of these fields are not “intellisensable” and cannot be accessed directly without having to manually enter the field name, as you can see from my code snippet below.

User Profile Properties Code

But its really easy to get the user field properties incorrect. A good example, is retrieving the office location. You would think the property name would be called “OfficeLocation” but its actually called “SPS-Location”.

Luckily SharePoint allows us to view and access all the user profile properties we require and even create our own custom fields.

Lets start by opening Central Administration and navigate to Manage Service Applications > User Profile Service Application, which will take you to the following page:

User Profile Service Application

Click on “Manage User Properties” to view a list of all user field properties SharePoint uses. To either rename the display name or view the actual property name, click on a field and press “Edit”.

Manage User Properties

The “Name” field (as highlighted below) is not editable and for a very good reason too! These are the property ID’s that we will call when wanting to retrieve their value. All default field names are not editable.

Edit User Property

As I stated earlier, you can create your own properties and call them whatever you want. But SharePoint already provides us with so many out-of-the-box, you probably won’t need to create anymore anytime soon.

Enable People Search in SharePoint 2010

In my last post, I showed you how to create an Enterprise Search page that consisted of both “Site” and “People” searches. Depending on how you have setup your search within Central Administration, you may find the “People” search not returning any results.

Before we start, there are a few things you need to check. Firstly, ensure you have the necessary search services in working order. If you can carry out site searches you should be fine. Secondly, ensure the User Profile service has been setup sufficiently so that features such as MySites and Profile databases are working.

In a straight-forward world, you would think that completing the steps above would be enough for SharePoint 2010 to allow you to search users within your site. But sadly we don’t live in a straight-forward world.

Open Central Administration and navigate to “Manage Service Applications”. Within the list of services, select “Enterprise Search Service Application”.

Manage Services Enterprise Search

In the “Enterprise Search Service Application” page, click on the “Content Sources” link you’ll find situated in the left hand navigation and open/edit your “Local SharePoint Sites” content source.

Manage Content Sources

In the Start Addresses section, you will see a box with entries similar to what I have in my SharePoint intranet below..well almost the same:

Content Sources Start Addresses

You will notice the line: “sps3://my-intranet” which tells SharePoint to call a specific web service hosted at that web address. In this case, the URL is the same one I use to access my main site collection. When you have added the “sps3://” line yourself press the “OK” button to save your changes.

There is just one last step we need to carry out: re-indexing our search. Navigate back to the “Enterprise Search Service Application” page and start full crawl.

Manage Content Sources Recrawl

Once this has completed all your user profiles should now be searchable.

Enterprise People Search