Jan 172014
 
If you’re like me and want your smiley face plastered all over your Lync conversations, then you may have found that Lync annoyingly makes you host your own picture:
 

lync

 
I found this very frustrating until I realized I had a LinkedIn account with a publicly-visible profile picture I could link to:
 

linkedin

 

To do this yourself

 
1. Update your linked-in picture (if need be)
 
2. Ensure your picture is publicly available
  • Account & Settings -> Privacy & Settings -> Change your profile photo & visibility
  • Ensure In addition to users I message, my profile photo is visible to… is set to Everyone
3. View your public profile
  • Click Profile
  • Click the link under your picture to view your public profile
  • Right-click your profile picture on your public profile

4. Copy the image URL

  • Right-click your profile picture on your public profile
  • Select “Copy image URL” in Chrome
  • Select “Copy” in IE
5. Set your Lync picture URL
  • Open Lync
  • Click your profile picture
  • Select Show a picture from a web address (as in the screenshot above)
  • Paste in the URL
  • Click OK
So now you’ve linked your Lync picture to a link to your LinkedIn picture… Easy!
Feb 252012
 

This is a classic SharePoint stumble: You want to delete a site (SPWeb), so you think “I’ll just use the Delete method. Obviously!” as anyone would. A few moments later and you’re staring at this obstinate and unshiftable error message:

Microsoft.SharePoint.SPException : Error deleting Web site “/web”. You can’t delete a site that has subsites.

Eventually you resign yourself to having to write some form of recursive function to delete every subsite’s subsite’s subsites one by one.

*sigh*

So let me make your life a little easier. Stick this static class in your reusable library of helpful classes (everyone’s got one), and forget about the problem forever:

public static class SPWebFix
{
    /// <summary>
    /// Deletes the Web site, optionally forcing the deletion of subsites
    /// </summary>
    /// <param name="web">The site to delete</param>
    /// <param name="force">Forcing deletion causes the site to be deleted even if it has subsites</param>
    /// <returns>The total number of sites deleted</returns>
    public static int Delete(this SPWeb web, bool force)
    {
        if (force || web.Webs.Count == 0)
        {
            // Call the recursive function
            return deleteWeb(web);
        }
        else
        {
            // Return 0 to indicate that this site was not deleted.
            return 0;
        }
    }

    private static int deleteWeb(SPWeb web)
    {
        int sitesDeleted = 1;

        foreach (SPWeb subWeb in web.Webs)
        {
            sitesDeleted += deleteWeb(subWeb);
        }

        web.Delete();
        web.Dispose();

        return sitesDeleted;
    }
}

Now whenever you want to recklessly delete a site and all its subsites, simply call the extension method version with the ‘force’ flag set to true:

deleteThisWeb.Delete(true);

That’s one tiny problem fixed.Smile

Oct 252011
 

I’ve written an article I’m particularly pleased with on my work blog:

SharePoint Questions: MSDN versus Stack Exchange

Graphs, statistics, comparison tables, and more! Here’s the intro:

SharePoint is an enormous heaving behemoth of machinery; full of spinning cogs, churning engines, and peculiar dials. We’ve all worked with parts of it, but not even those that created it understand all of its inner workings.

So where do we go when the wheel that goes ‘whir’ is going ‘squeakity’? Or when we’re having trouble bolting on some shiny new levers? What we need is an expert in that area.

Aug 162011
 

Writing code to get or set data in a lookup field (SPFieldLookup) or its descendant the User field (SPFieldUser) can be a real pain in the eyes. Thankfully there’s a handy couple of classes that can make life easier.

If you’ve ever frowned at “;#” delimiters, and begrudgingly twisted a for clause to check every other line, then you should most definitely read on.

A bit of background

Most complex field types have a Value class; a class that handles serialising and deserialising an item’s data for that field. If the field can have multiple values then there is often also a Collection class (a generic collection in the form List<Value>).

For lookups these classes are called SPFieldLookupValue and SPFieldLookupValueCollection. For User selections these are SPFieldUserValue and SPFieldUserValueCollection.

Getting single items

If you only have one value in a lookup, then this can be accessed using the following:

SPListItem item = SPContext.Current.List.GetItemById(1);
 
if (item["LookupField"] != null)
{
     string fieldValue = item["LookupField"].ToString();
     SPFieldLookupValue value = new SPFieldLookupValue(fieldValue);
     int lookupListItemID = value.LookupId;
     string lookupListValue = value.LookupValue;
}

Not a single split string in sight. To do the same for a single user field, you do the following:

SPListItem item = SPContext.Current.List.GetItemById(1);
 
if (item["UserField"] != null)
{
     string fieldValue = item["UserField"].ToString();
     SPFieldUserValue value = new SPFieldUserValue(SPContext.Current.Web, fieldValue);
     SPUser user = value.User;
}

The SPWeb passed into the constructor above is used to resolve the User; if you’re writing cross-site code make sure you pass a Web that recognises the User.

Setting single items

Setting lookups is quite straight forward:

SPListItem item = SPContext.Current.List.GetItemById(1);
int id = 1;
item["LookupField"] = new SPFieldLookupValue(id, string.Empty);
item.Update();

id is the item ID in the lookup list, and the string.Empty is the optional (as far as I can tell) display value. The display value is populated using the ID once the item is updated, so we needn’t bother getting it ourselves.

Setting a single user field couldn’t be easier, and requires no special tools, classes, or qualifications:

item["UserField"] = SPContext.Current.Web.CurrentUser;

Multiple items

Now we’re getting into more interesting territory. Multiple choice Lookups can be accessed using the previously-mentioned SPFieldLookupValueCollection. This is a collection of SPFieldLookupValue objects that each represent one of the values.

The collection can be used to get information like this:

SPListItem item = SPContext.Current.List.GetItemById(1);
if (item["LookupField"] != null)
{
     string fieldValue = item["LookupField"].ToString();
     SPFieldLookupValueCollection values = new SPFieldLookupValueCollection(fieldValue);
     foreach (SPFieldLookupValue value in values)
     {
         int lookupListItemID = value.LookupId;
         string lookupListValue = value.LookupValue;
     }

}

And to set the item data like this:

SPListItem item = SPContext.Current.List.GetItemById(1);
SPFieldLookupValueCollection values = new SPFieldLookupValueCollection();
values.Add(new SPFieldLookupValue(1,string.Empty));
values.Add(new SPFieldLookupValue(3,string.Empty));
item["LookupField"] = values;
item.Update();

The SPFieldUserValueCollection is used in almost exactly the same way. The only differences are that the constructors require an SPWeb, and SPUser.ID is used for the LookupID.

Pretty neat

Well, I thought so.

All this was probably old news to some, but it was a Christmas stocking of happy surprises for me when I found it. :)

%d bloggers like this: