Building an iOS App to access Office 365 and SharePoint – Part 3

Jordan Melliadis is an Intern at ThreeWill working on the ThreeWill Labs Team.


This blog post outlines the steps needed to utilize the SharePoint Search REST API within an iOS application using the ADALiOS library and a custom ASP.NET Web API 2.0 project. It is the final post in a series of three blog posts revolving around creating a native iOS application that connects to O365 and SharePoint Online. If you followed along from the first blog post, then you should have a project that builds successfully with the ADALiOS library added and authenticates a user to access their content from Office 365 and SharePoint Online (previous installments can be found here and here).

The Problem with OAuth and the SharePoint Search REST API,

If there is one big issue with the SharePoint Search REST API it is that it is disabled for anonymous users by default. The problem rears its head when trying to use the OAuth 2.0 access token given to your application by the ADALiOS library to authenticate to the Search REST API. There are many examples of why you would want to use the search API within your native application. For example, we needed to search and find all of the webs and sites available to the current user for our application. There are ways to enable anonymous search for your site collections, but if you are trying to build a multi-tenant application, this may not be possible to accomplish. Luckily, there is a way to solve this issue without enabling anonymous search: creating a custom ASP.NET Web API to allow User Impersonation to the SharePoint Search REST API.

A Custom ASP.NET Web API 2.0 to allow User Impersonation

To start, you need to create a new Web API project from within Visual Studio 2013. The API needs to be configured for User Impersonation within Azure Active Directory. For complete details on creating the application and configuring it correctly, refer to Kirk Evan’s blog post on calling Office 365 APIs from your Web API on behalf of a user. You can follow this blog post all the way through if you just want to run his example; however, if you want to follow the SharePoint search example then stop once you have installed the Active Directory Authentication Library in the “Using ADAL” section of his post. I will only quickly recap these steps here:

  • Click your Tenant directory in the Azure Portal
  • Click Applications,then click your “Native client application” entry
  • Click Configure in the menu bar (top of page)
  • Download the manifest and add the appPermissions


You can now create a new class within the API; I called mine SharepointOnlineSearch. This is the class that will take the access token provided by the native application and create a user impersonation access token to Office 365 from it within the Web API. It will also be used to call the SharePoint Search Web API and get the list of all webs and sites for the tenant.

using Microsoft.IdentityModel.Clients.ActiveDirectory;
using System;
using System.Globalization;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
using System.Xml.Linq; 

namespace TWSharepointAppWebApi.Models
    public class SharepointOnlineSearch
        /// <summary>
        /// Get the access token
        /// </summary>
        /// <param name="clientId">Client ID of the Web API app</param>
        /// <param name="appKey">Client secret for the Web API app</param>
        /// <param name="aadInstance">The login URL for AAD</param>
        /// <param name="tenant">Your tenant (eg kirke.onmicrosoft.com)</param>
        /// <param name="resource">The resource being accessed</param>
        /// <returns>string containing the access token</returns>
        public static async Task<string> GetAccessToken(
            string clientId,
            string appKey,
            string aadInstance,
            string tenant,
            string resource)
            string accessToken = null;
            AuthenticationResult result = null; 

            System.Diagnostics.Trace.WriteLine("Getting access token..."); 

            ClientCredential clientCred = new ClientCredential(clientId, appKey);
            string authHeader = HttpContext.Current.Request.Headers["Authorization"]; 

            System.Diagnostics.Trace.WriteLine("Client Cred : " + clientCred.ClientId); 

            System.Diagnostics.Trace.WriteLine("Auth header : " + authHeader); 

            string userAccessToken = authHeader.Substring(authHeader.LastIndexOf(' ')).Trim();
            UserAssertion userAssertion = new UserAssertion(userAccessToken); 

            System.Diagnostics.Trace.WriteLine("User Assertion : " + userAssertion.Assertion); 

            string authority = String.Format(CultureInfo.InvariantCulture, aadInstance, tenant); 

            System.Diagnostics.Trace.WriteLine("Authority : " + authority); 

            AuthenticationContext authContext = new AuthenticationContext(authority); 

            System.Diagnostics.Trace.WriteLine("Auth Context : " + authContext.Authority);
            try {
                result = await authContext.AcquireTokenAsync(resource, userAssertion, clientCred);
                accessToken = result.AccessToken;
            catch (Exception e) {
                System.Diagnostics.Trace.WriteLine("Error : " + e.Message);

            System.Diagnostics.Trace.WriteLine("Got access token..."); 

            return accessToken;

        /// <summary>
        /// Get all sites
        /// </summary>
        /// <param name="siteURL">The URL of the root SharePoint site</param>
        /// <param name="accessToken">The access token</param>
        /// <returns>Http response from SharePoint</returns>
        public static async Task<HttpResponseMessage> GetAllSites(
            string siteURL,
            string accessToken)
            // Call the O365 API and retrieve the user's profile.
            string requestUrl = siteURL + "_api/search/query?querytext='path:" + siteURL + "*'&refinementfilters='contentclass:or(STS_Web,STS_Site)'&rowLimit=100&trimDuplicates=false"; 

            System.Diagnostics.Trace.WriteLine("Building API request...");
            System.Diagnostics.Trace.WriteLine("Request Url : " + requestUrl); 

            HttpClient client = new HttpClient();
            HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, requestUrl); 

            System.Diagnostics.Trace.WriteLine("Request : " + request.RequestUri.AbsolutePath); 

            request.Headers.Add("Accept", "application/json; odata=verbose"); 

            System.Diagnostics.Trace.WriteLine("First header added..."); 

            request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken); 

            System.Diagnostics.Trace.WriteLine("Second header added..."); 

                HttpResponseMessage response = await client.SendAsync(request); 

                if (response.IsSuccessStatusCode)
                    //string responseString = await response.Content.ReadAsStringAsync(); 

                    System.Diagnostics.Trace.WriteLine("API Request successful"); 

                    return response;
            catch (Exception e)
                System.Diagnostics.Trace.WriteLine("Error : " + e.Message);

            // An unexpected error occurred calling the O365 API.  Return a null value.
            return (null);

Now from within the ValuesController, we can utilize our newly created class within the GET method to return the data from the SharePoint Search REST API call.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using TWSharepointAppWebApi.Filters;
using System.Configuration;
using System.Threading.Tasks; 

namespace TWSharepointAppWebApi.Controllers
    public class ValuesController : ApiController
        // GET api/values
        public async Task<HttpResponseMessage> Get()
            string clientID = ConfigurationManager.AppSettings["ida:ClientID"];
            string appKey = ConfigurationManager.AppSettings["ida:AppKey"]; 

            string aadInstance = ConfigurationManager.AppSettings["ida:AADInstance"];
            string tenant = ConfigurationManager.AppSettings["ida:Tenant"];
            string resource = ConfigurationManager.AppSettings["ida:Resource"]; 

            string accessToken = await Models.SharepointOnlineSearch.GetAccessToken(
            var ret = await Models.SharepointOnlineSearch.GetAllSites (

            System.Diagnostics.Trace.WriteLine("Ret : "  + ret.Content.ToString());
            return ret;

        // POST api/values
        public void Post([FromBody]string value)

        // PUT api/values/5
        public void Put(int id, [FromBody]string value)

        // DELETE api/values/5
        public void Delete(int id)

I went ahead and appended the tenant to the end of the “ida:AADInstance” key in the web.config file instead of leaving it as a formatted string as Kirk Evans does in his example. If you choose not to do this, then you will need to add a little logic to create the full AADInstance value from the current value and the ida:Tenant value. With this code, you should be able to run locally with no issues. If you try accessing the values API with a GET request, an unauthorized message should be returned because you do not have the OAuth 2.0 access token.

You can now give your native application permissions to access your custom web API from within the configuration screen on Azure, but at this point, it will only be hitting the localhost API.

image 1 localhost


Publishing to Azure “Gotchas”

At this point, you should have a working API locally. But what you really want is a published API on Azure that can be accessed from your iOS application easily. Here are a few “gotchas” you may run into when publishing your web API to Azure.

  1. Make sure you check Enable Organizational Authentication from within the publishing “Settings” menu within Visual Studio. When this is selected, Visual Studio will prompt you to sign in to your tenant. This will also allow Visual Studio to create the new application in Azure Active Directory that points to the published Azure Website instead of localhost.
  2. Make sure you also copy the APP ID URI from the VS created Active Directory application that points to the published Azure Website into the web.config file as the new Audience for the Web API. Then you need to re-publish the app to have the new Audience URL. This should be in the form of “https://<tenant>.onmicrosoft.com/WebApp-XXXXXX.azurewebsites.net”.


  3. In the VS created Active Directory application, you need to go through the same steps to add the User Impersonation permissions as you did with the application pointed to local host. This means downloading the app manifest, adding the impersonation code, and uploading it back to Azure.

Using the Multi-Resource Refresh Token

Now that you have a published custom Web API that connects to Office 365 and SharePoint Online with User Impersonation, you need to give your native client application permissions to access the API on Azure. From the management portal, select your native client applications and add your newly created permission from the configuration tab.



Given that the native client application has the correct permissions, you should be able to authenticate to the API and access the SharePoint Search results.

If you have followed from the previous blog post, then your application is already handling authentication to Office 365 and SharePoint Online. With your newly created application permissions, once you have authenticated to one resource, you now receive a “multi-resource refresh token.” This refresh token can be used to refresh an access token to each of your application’s resources and is cached as the refresh token for each source by the ADALiOS library. Thus, to access the newly created custom web API, you can simply call the aquireTokenWithResource: method with the API “Audience” URL as the resource.

NSString* path = [[NSBundle mainBundle] pathForResource:@"ADALInfo" ofType:@"plist"]; 

    NSDictionary* ADAL = [NSDictionary dictionaryWithContentsOfFile:path];
    ADAL = [NSDictionary dictionaryWithDictionary:[ADAL objectForKey:@"AAD Instance"]]; 

    ADAuthenticationContext* authContext;
    ADAuthenticationError *error;
    authContext = [ADAuthenticationContext authenticationContextWithAuthority:[ADAL objectForKey:@"Authority"] error:&error]; 

    NSURL *redirectUri = [NSURL URLWithString:[ADAL objectForKey:@"RedirectUri"]];
        [authContext acquireTokenWithResource:[ADAL objectForKey:@"ApiResource"]
                                 clientId:[ADAL objectForKey:@"ClientId"]
                          completionBlock:^(ADAuthenticationResult *result) {
                              if (AD_SUCCEEDED != result.status){
                                  // display error on the screen
                              else {

This code will authenticate the application to the web API without any user action, provided that there is already a multi-resource refresh token cached (which there should be if this authentication is called after the authentication to Office 365 and SharePoint Online). You can set the promptBehavior attribute to AD_PROMPT_NEVER so that the user will never be prompted even if the authentication fails because there is no refresh token if this authentication is happening at a point in the application where it does not make sense to allow the login screen to pop up. If this does happen, an appropriate error will be returned explaining that the authentication failed because there was no refresh token present and AD_PROMPT_NEVER was set. Again, this code assumes that the API “Audience” URL that was set in the web.config file is stored in the .plist file of the iOS application under the “ApiResource” key.

With the application authenticated to the web API, it can now access the API search results through the use of an NSURLConnection with the authorization header set to the access token. I added “SearchAPIUrl” as another key in the .plist file in the iOS application with its value set to the URL of my custom web API.

NSString* path = [[NSBundle mainBundle] pathForResource:@"ADALInfo" ofType:@"plist"]; 

    NSDictionary* ADAL = [NSDictionary dictionaryWithContentsOfFile:path];
    ADAL = [NSDictionary dictionaryWithDictionary:[ADAL objectForKey:@"AAD Instance"]]; 

    NSURL *apiUrl = [NSURL URLWithString:[[ADAL objectForKey:@"SearchAPIUrl"] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; 

    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:apiUrl]; 

    ADAuthenticationError* error; 

    self.context = [ADAuthenticationContext authenticationContextWithAuthority:[ADAL objectForKey:@"Authority"] error:&error]; 

    ADTokenCacheStoreKey* key = [ADTokenCacheStoreKey keyWithAuthority:[ADAL objectForKey:@"Authority"] resource:[ADAL objectForKey:@"ApiResource"] clientId:[ADAL objectForKey:@"ClientId"] error:&error];
    id<ADTokenCacheStoring> cache = self.context.tokenCacheStore;
    ADTokenCacheStoreItem* item = [cache getItemWithKey:key userId:nil]; 

    NSString *authHeader = [NSString stringWithFormat:@"Bearer %@", item.accessToken]; 

    [request setValue:authHeader forHTTPHeaderField:@"Authorization"]; 

    [request setValue:@"application/json" forHTTPHeaderField:@"accept"]; 

    NSOperationQueue *queue = [[NSOperationQueue alloc]init]; 

    [NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) { 

        if (error == nil){ 

            NSError *jsonError; 

            NSObject *object = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:&jsonError]; 

            NSMutableArray *refreshResults = [[[[[[[object valueForKey:@"d"] objectForKey:@"query"] objectForKey:@"PrimaryQueryResult"] objectForKey:@"RelevantResults"] objectForKey:@"Table"] objectForKey:@"Rows"] objectForKey:@"results"]; 

            //any logic with the results goes here 

            dispatch_async(dispatch_get_main_queue(), ^{
               //any updates to the UI here


        else {
            //may want to handle the error here
            dispatch_async(dispatch_get_main_queue(), ^{
               //any updates to the UI here



At this point, you have a project that builds correctly using the ADALiOS library, authenticates the user to both SharePoint Online and a custom ASP.NET Web API 2.0, and can take advantage of both the SharePoint REST API and SharePoint Search REST API. You can now build native applications that seamlessly connect with SharePoint data using an OAuth 2.0 access token and refresh token.

read more
Jordan MelliadisBuilding an iOS App to access Office 365 and SharePoint – Part 3

Do You See SharePoint As Half Full Or Half Empty?

Tim is a Senior Consultant at ThreeWill. He has 15 years of consulting experience designing and developing browser-based solutions using Microsoft technologies. Experience over the last 8 years has focused on the design and implementation of SharePoint Intranets, Extranets and Public Sites.

As a SharePoint Consultant who has consulted at many different companies small and large, I have often experienced negative initial reactions when mentioning SharePoint.

The reasons have ranged from things like “SharePoint is slow” to other things like the “SharePoint navigation is confusing”. And I have to admit, there have been times I have used SharePoint sites that were both slow and confusing. The good news is that both of these can be improved so that they do not need to become a roadblock to using an otherwise useful product. But beyond merely removing these barriers, the good news is that there are many features that SharePoint provides that many users have never come to understand and appreciate and my goal is to help raise awareness of these features.

What I have learned over time is that most users’ concept of SharePoint is that it is simply a document repository…

They see it as a ”a place my boss forces me to put my files that takes more time and effort than storing them locally or putting them on a file share”. SharePoint is generally a product that has been introduced to the organization by the IT department for work teams to collaborate and usually with little or no training on SharePoint provided. And while storing documents is certainly a valid use of SharePoint, there is so much more capability than most users realize or have been given the rights to leverage in their work group or department.

On occasion, I have the opportunity to sit down with motivated employees who like to learn and I describe to them some of the features within SharePoint that I think will interest them.

Most users are surprised to hear about these capabilities and are eager to figure out how they can begin to use them.

My goal in this blog series is to share a few of what I consider to be the most underutilized features of SharePoint that can be leveraged for both personal productivity and business process improvements.

These underutilized features include:

  • Custom Lists
  • Notifications and Workflow
  • Security

After discussing these features individually, I’ll conclude with a discussion of how these features can be combined together to create Business Applications that can help support and automate some of your current business processes.

And before you assume that you need a developer or technical person to take advantage of these features, know that all of these are available to end-users of SharePoint and are configurable through the SharePoint UI or through SharePoint Designer.

Stay tuned. I look forward to sharing more about these underutilized features with you and hearing from you about any questions or comments on these topics.

By the way…


We thought you would enjoy this take on how different people see the half full/empty glass (source)…

The optimist says the glass is half full.

The pessimist says the glass is half empty.

The project manager says the glass is twice as big as it needs to be.

The professional trainer does not care if the glass is half full or half empty, he just knows that starting the discussion will give him ten minutes to figure out why his powerpoint presentation is not working (@jbutweets – thought you would enjoy this one!)

The consultant says let’s examine the question, prepare a strategy for an answer, and all for a daily rate of…

The engineer says the glass is over-designed for the quantity of water.

The computer programmer says the glass is full-empty.

read more
Tim CoalsonDo You See SharePoint As Half Full Or Half Empty?

Dr. Scriptlove: SharePoint and JavaScript

John Underwood is a Technical Evangelist at ThreeWill. He has nearly thirty years of software development experience. He is an experienced technical instructor with superior presentation skills and is proficient in delivering standard curriculum as well as developing and delivering custom curriculum.


It’s not because…

I’m an old curmudgeon that resists new things; after all, I do consulting and teaching, and staying up on the latest technologies is an important and enjoyable part of my professional life.

It’s not because…

I’m a zealot for a particular language; I think most modern languages have pros and cons.

Really, my dislike boils down to this:

JavaScript feels like a major step backward in the evolution of programming, and I see it as an easy path to brittle, buggy, unmaintainable code.


Well, I recently attended a training class on SharePoint 2013 and the instructor made an excellent case on writing SharePoint Hosted apps (if you’re not familiar with the application hosting models in SharePoint 2013, please reference this article).




But, if I’m going to do that with any sort of professional satisfaction then I want to really feel like I’m writing elegant, beautiful, maintainable code that I can be proud of.

If you find yourself in a similar circumstance, then let me recommend a three-step process to get you jump-started.

  1. Read this book. More than any other text I’ve seen, JavaScript: The Good Parts does a good job of acknowledging my concerns about JavaScript and providing real answers to address them. Beyond that, it’s just a treasure trove of good practices to engage and bad practices to avoid. It opened my eyes to some of the expressiveness of the language, and while I’m not sure I can call it “love” yet, I’ve certainly gotten past my loathing.
  2. Embrace jQuery. Sure, the old-hands at JavaScript know about this already, but if you’re new to the party then don’t bother wondering whether or not you need this: you need it, and doing any kind of browser-based programming without it just seems unthinkable at this point.
  3. Don’t abandon your architectural roots. Those of us that are schooled in programming know that certain patterns work on building scalability, reusability, and maintainability into our code. Your multi-tiered, loosely-coupled, MVC, MVVM learning still apply here. (By the way, Knockout is an excellent way to implement some of these patterns). It just may take a little more effort on your part to stay architecturally sound since the language and the tooling makes it easy to pollute your architecture.


Go forth and write some elegant code!


read more
John UnderwoodDr. Scriptlove: SharePoint and JavaScript

The Final Four (or Five) – SharePoint Migration Tools

Will Holland is a Senior Software Engineer at ThreeWill. Will has proven to be adept at understanding a client’s needs and matching them with the appropriate solution. Recently he’s developed a passion for working with .NET, MVC, and cloud-based solutions such as Microsoft Azure and Office 365.

For the past year, I have been involved in a project involving an enterprise level migration from SharePoint 2007 to SharePoint 2010. Without getting into too many gritty details, this particular client determined that the best approach to complete the migration in a manner that conformed to their practices and procedures they wanted to purchase a third party tool. Many tools were considered and many sales-folk harassed. In the end, the list of options came down to five different tools. In this post I’ll talk about the different tools, the pros and cons of each, and some of the client-specific requirements a selection had to meet.

The Yardstick – How We Measured A Tool’s Worth

As I mentioned, there were five different tools that made it to the ‘finals’:

  1. MetaVis’ Architect Suite,
  2. Quest’s Migration Suite for SharePoint,
  3. AvePoint’s DocAve SharePoint Migrator,
  4. Axceler’s Davinci,
  5. and Idera’s SharePoint Migration Suite.

My client also had several key points that they wanted to use to measure and compare the tools to each other. First, with SharePoint 2013 being added to the mix, my client has begun consideration of a cloud-based environment and, as such, they preferred that any tool they purchased also support migrating to such an environment.

Next, due to internal governance processes the preferred tool needed to be ‘agent-less’ – nothing should require an installation into production. Each production install must go through a lengthy and complicated review process before being allowed. Since our plan called for multiple test iterations the review process would need to be repeated several times, further adding to the amount of time taken to complete the migration.

The other points are a bit more transparent than the first two mentioned. Cost was, obviously, a factor as well as any impact to production up-time. The licensing scheme used by the vendor was another concern. There are a few different schemes commonly used. Some vendors use an “Unlimited” license meaning that you can migrate as much and as often as you want. Other vendors license you based on an amount of data being migrated, usually measured in GB. Of those, some don’t count “test” iterations against your license, some do. Still others license individual users.

The Competitors – A Break Down

MetaVis: Architect Suite

Website – http://www.metavistech.com/category/architect-suite

Cloud Migration Support: Yes
Additional Cost for Cloud: No
Agent-less Install: Yes
Up-time Impact: None
Licensing Scheme: Unlimited (Not priced per GB)

The tool from MetaVis is a very well rounded tool that offers its users the ability to migrate on a variety of levels, ranging from an entire farm to a single document. It will also migrate metadata, all Out-of-box and SharePoint Designer workflows, web parts and permissions.

Quest: Migration Suite for SharePoint

Website – http://www.quest.com/migration-suite-for-sharepoint/

Cloud Migration Support: Yes
Additional Cost for Cloud: No
Agent-less Install: Yes
Up-time Impact: None expected (Could never get an official ‘guarantee’ from them)
Licensing Scheme: Per GB migrated.

The most important thing to note about the Quest tool is that it is, virtually the same tool offered by Metavis. In fact, it is a licensed version of the Metavis tool. If you don’t mind the ‘Per GB migrated’ licensing you may be able to get this a bit cheaper than the Metavis version with no feature loss.

AvePoint: DocAve SharePoint Migrator

Website – http://www.avepoint.com/sharepoint-to-sharepoint-migration-docave/

Cloud Migration Support: Yes
Additional Cost for Cloud: No
Agent-less Install: No
Up-time Impact: None
Licensing Scheme: Per GB migrated

AvePoint is a fairly well established player in the migration market these days. There tools are reportedly solid but, for this customer, the fact that they required something being installed to production was a no-go.

Axceler: Davinci

Note : Since I completed my review of Davinci Axceler has removed Davinci and now has  “ControlPoint for SharePoint Migration.” I cannot say whether their new tool is simply a rebranded Davinci or a complete overhaul.

Website – http://www.axceler.com/products/controlpoint-sharepoint-products/sharepoint-migration/index

Cloud Migration Support: No
Additional Cost for Cloud: N/A
Agent-less Install: No
Up-time Impact: Unclear (Sales rep couldn’t directly answer and never followed-up with us).
Licensing Scheme: Mixed. Must purchase both a license for each user and a ‘Per GB’ license.

Axceler is known for their ControlPoint software but has just recently decided to jump into the Migration game and, well, it shows a bit when talking with them. Eventually, the conversation always ends up back at ControlPoint, even during what is supposed to be a demo of Davinci.

Idera: SharePoint Migration Suite

Website – http://www.idera.com/SharePoint/sharepoint-migration-suite/

Cloud Migration Support: No
Additional Cost for Cloud: N/A
Agent-less Install: Yes
Up-time Impact: None
Licensing Scheme: Single User License

Idera, like Quest, has opted to license Metavis’ software. Oddly enough, though, they don’t support cloud Migrations at this point which almost immediately disqualified them for my client.

So, Who Ended Up The Winner?

For my customer, the decision was made to go with Metavis. It was the only one of the five that meet all three of their ideals. There were a few, more minor differences between the different software but in the end they all typically supported the same functionality. Price didn’t play into my customer’s decision as much as functionality. Metavis was dead center on pricing relative to the others; Quest was the cheapest while Axceler was the most expensive (they quoted us buying Control Point and adding Davinci at no additional cost).

What works for your migration might be a bit different than what worked for my client. Also, there are other tools out there that weren’t considered (Metalogix comes to mind) that might work better for your needs. Each migration is somewhat different and every client is going to have slightly different priorities.

Editor Note – On other ThreeWill projects, we’ve had experience with many of the tools evaluated and as Will points out we believe that one tool doesn’t fit all.  Let us know if we can help you with evaluating options by contacting us.  Also, be sure to read Bo George’s SharePoint Migration Options to learn more about using built-in tools for migrations.

Do You Have A Favorite?

Let me know your experience with evaluating options for your company or clients – I’m interested to compare your experiences with mine so please leave comments below.

Here’s an unscientific poll to see if there is an obvious favorite.  Share your vote to see results.

read more
William HollandThe Final Four (or Five) – SharePoint Migration Tools

Adding jQuery to SharePoint

John Underwood is a Technical Evangelist at ThreeWill. He has nearly thirty years of software development experience. He is an experienced technical instructor with superior presentation skills and is proficient in delivering standard curriculum as well as developing and delivering custom curriculum.

Editor’s Note – If you’re looking to add AngularJS to SharePoint, check out this post.

Options, Options, Options

As I research and learn more about SharePoint programming, I occasionally come across blog posts that start with titles like “the best way…” or “the correct way…” to accomplish a certain task. If there’s anything I’ve learned with SharePoint along the way, it’s that there is rarely one correct and proper way of doing things; rather, there are usually a variety of approaches, each with its own pros and cons. To that end, this post attempts to document some of the ways one might include jQuery in a SharePoint site.

Note that this article isn’t intended to be a tutorial for jQuery (click here to learn more about jQuery). The presumption is that you’re reading this because you already know something about the power of jQuery and you wish to unleash that power in the context of SharePoint 2010. Also, note that I’m not trying to document every single way this problem can be solved; I’m just serving up some recipes that have worked for me. In addition, this article assumes that you already have some knowledge about SharePoint programming (such as using Visual Studio 2010 to create SharePoint projects). Finally, note that the demos below assume that you have Visual Studio 2010 and that you’re working against a Team Site.

A Fork in the Road

As Yogi Berra is alleged to have said, “If you see a fork in the road… take it!” In our case, there are several forks in the road:

  1. Do you need to include jQuery for the majority of the pages in a site, or just for one or two?
  2. Where do you need to use jQuery (i.e. in a Visual Web Part, on an Application Page, on a Site Page)?
  3. Will you be working with a Sandboxed Solution?

The answers to these questions will influence which of the following recipes will work for you.

Recipe 1: Loading jQuery from a Document Library with a Custom Action

This approach is useful when you need to have jQuery available to most or all of the pages in a site. It is also useful in the scenario where you’re working in a Sandboxed Solution, since such solutions cannot store files in the SharePoint Root (or “14 hive”). Additionally, it is useful in that .js files stored in a document library can be easily maintained without administrator intervention.

On the downside, storing .js files in a library means they could accidentally or intentionally be deleted or changed, resulting in improper functioning of the application.

This recipe also includes a small bit of custom jQuery code that will be included on each page for demonstration.

1. Create a Visual Studio 2010 Empty SharePoint Project (either Farm Solution or Sandboxed Solution).

2. Add a Module named DeployJQuery; delete the sample.txt file and add your jQuery file to the module.

DeployJQuery Module

3. Modify the Elements.xml file for the DeployJQuery module as follows (note that all line numbers are provided for convenience only, and should not be included in source):

&lt;xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;Elements xmlns=&quot;https://schemas.microsoft.com/sharepoint/&quot;&gt;
&lt;Module Name=&quot;DeployJQuery&quot;&gt;
&lt;File Path=&quot;DeployJQuery\jquery-1.6.4.js&quot;&amp;nbsp;Url=&quot;SiteAssets/jquery-1.6.4.js&quot; /&gt;

4. Add a second Module named DeployCustomJS; rename the sample.txt file to Custom.js.

5. Modify the contents of the Custom.js file:

$(document).ready(function () {
$('.static.menu-item').mouseover(function () {
$(this).fadeTo(&quot;fast&quot;, 0.33);
$(this).fadeTo(&quot;fast&quot;, 1);

6. Modify the Elements.xml for the DeployCustomJS module as follows:

&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;Elements xmlns=&quot;https://schemas.microsoft.com/sharepoint/&quot;&gt;
&lt;Module Name=&quot;DeployCustomJS&quot;&gt;
&lt;File Path=&quot;DeployCustomJS\Custom.js&quot; Url=&quot;SiteAssets/Custom.js&quot; /&gt;

7. Add an Empty Element named LoadJQuery and then modify its Elements.xml file as follows:

&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;Elements xmlns=&quot;https://schemas.microsoft.com/sharepoint/&quot;&gt;
&lt;CustomAction Id=&quot;BlogSample.LoadJQuery&quot; ScriptSrc=&quot;~site/SiteAssets/jquery-1.6.4.js&quot;
Location=&quot;ScriptLink&quot; Sequence=&quot;10020&quot; /&gt;

8. Add a second Empty Element named LoadCustomJS; modify its Elements.xml to match the following:

&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;Elements xmlns=&quot;https://schemas.microsoft.com/sharepoint/&quot;&gt;
&lt;CustomAction Id=&quot;BlogSample.Script&quot;
Location=&quot;ScriptLink&quot; Sequence=&quot;10030&quot; /&gt;

9. Deploy the project.

10. Navigate to the site. As you float your mouse over the menu items in the quick-launch menu you should see them pulse from solid to opaque to solid.

Recipe 2: Loading jQuery from SharePoint Root using ScriptLink Control

This is useful when you’re using jQuery on an application page or a Visual Web Part; both can easily be configured to use one or more ScriptLink controls.

Obvious limitations include: jQuery is only made available to one page at a time; use of ScriptLink control is limited to certain kinds of pages; and deployment of files to SharePoint root precludes the use of this technique for Sandboxed Solutions.

1. Create a new Farm Solution in Visual Studio 2010.

2. Add a new SharePoint mapped folder to the project; the mapped folder should point to {SharePointRoot}\Template\LAYOUTS\1033.

3. Underneath the mapped folder create a new mapped folder with the same name as your project (in my case, Recipe2 is the name of the sample project). You can see the results below:

4. Deploy the project (this is done here so the ScriptLink control won’t produce an error on a later step when you try to use the .js file).

5. Add a Visual Web Part to the project and name it jQueryPart.

6. Add a ScriptLink control to the web part (see source below). Set the ScriptLink’s Name property to <projectname>/jquery-1.6.4.js (where <projectname> is the name of the folder you created in step 3 above).

&lt;SharePoint:ScriptLink ID=&quot;ScriptLinkJQuery&quot; runat=&quot;server&quot;
Name=&quot;Recipe2/jquery-1.6.4.js&quot; /&gt;

7. Add the following markup to the web part just below the ScriptLink:

&lt;script type=&quot;text/javascript&quot;&gt;
var colors = ['lime', 'aqua', 'orange'];
var i = 0; $(document).ready(function () {
$('#sample').css('background-color', colors[i]);
$('#sample').click(function () {
if (i &gt;= colors.length) { i = 0; }
$(this).css('background-color', colors[i]);

&lt;span id=&quot;sample&quot; style=&quot;cursor: pointer&quot;&gt; Click me &lt;/span&gt;

8. Deploy the project.

9. Navigate to the site and then navigate to the Site Pages library.

10. Add a new page named jQueryTest.

11. On the jQuery test page click Insert tab | Web Part | Custom | jQueryPart; then click the Add button to place the part on the page as follows:

12. Click the Save and Close button to save your changes.

13. Click the “Click me” text and observe the color change.

Recipe 3: Loading jQuery from a Content Delivery Network (CDN) using the Content Editor web part

This approach is beneficial when you only need to use jQuery on one or a small number of site pages (both Wiki and Web Part Pages). It is also advantageous in that it does not require storing any extra files on the SharePoint server: the jQuery source is loaded from a Content Delivery Network while the jQuery code that you author is embedded directly into the page itself. Additionally, this solution doesn’t violate any of the tenets of Sandboxed Solutions.

Obviously this isn’t a useful approach for site-wide jQuery needs. Also, there may be some rare cases where you can’t accomplish what you want with this approach because the jQuery links and source are placed down within the document as opposed to the preferred approach of locating script in the <head> section of the HTML markup.

1. Navigate to the site pages library and add a new page named jQueryContent.

2. Add a Content Editor Web Part to the page.

3. Edit the Content Editor Web Part and click on the “Click Here to add new content” link.


4. On the Ribbon select HTML | Edit HTML Source.

5. In the Edit HTML Source dialog enter the following markup and then click OK:

&lt;script language=&quot;javascript&quot; type=&quot;text/javascript&quot; src=&quot;https://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js&quot;&gt; &lt;/script&gt; &lt;script language=&quot;javascript&quot; type=&quot;text/javascript&quot;&gt;
$(document).ready(function() { alert(&quot;jQuery&quot;); });

6. Click OK to stop editing web part, then click Save and Close button.

7. The page should now display a popup as follows:

What about Master Pages?

One can certainly embed the needed jQuery references directly in a master page, using either a ScriptLink control or a simple <script> tag. However, I’ve chosen not to focus on that approach simply because I’m inclined to view modifying the Master Page as something I don’t want to do unless I absolutely must. If you’ll be changing the Master Page as a part of a bigger branding solution then it certainly makes sense to embed jQuery there; otherwise, Recipe 1 above will give you similar site-wide functionality in what is perhaps an easier and safer way.

Learning to be a great cook

One of the attributes of a great cook is the ability to synthesize ingredients to come up with something new and delicious. The same can be said of these SharePoint recipes. For example, the use of a Content Delivery Network to serve up jQuery isn’t limited to just one recipe. Experience and experimentation will allow you to find the mix of ingredients that works best for your masterpiece.

Careful not to burn yourself…

There are always hazards when cooking: hot stoves, sharp knives, and dropped pans. Likewise there are hazards involved in integrating jQuery with SharePoint, including the following:

  • The risk that some other developer would introduce their own jQuery solution, resulting in a possible conflict of versions or files.
  • Failure to test thoroughly resulting in erratic behavior in the SharePoint UI.
  • The lack of Microsoft providing an “officially sanctioned” approach to introducing jQuery into SharePoint means that any introduction of jQuery involves a certain amount of wizardry.

Hazards notwithstanding, the power of jQuery makes it a compelling option for customizing and enhancing the SharePoint UI.

read more
John UnderwoodAdding jQuery to SharePoint

ThreeWill Hero – Clint Padgett

Danny serves as Vice President of Marketing at ThreeWill. His primary responsibilities are to make sure that we are building partnerships with the right clients and getting out the message about how we can help clients.

Helping Rembrandt Paint Masterpieces

A couple of years back, Atlassian introduced us to another company based out of Australia that they thought would be good for us to talk to because of similar cultures. The company was Customware. I had skype conversation with their CEO, Rob Castenada, and about midway through the conversation he mentioned something pretty insightful…”You guys are like us, you help the Rembrants of the world to paint their masterpieces.” For us, we help the most successful software companies in the world build software products that run on or are integrated with SharePoint. In the case of Customware, the focus on Atlassian’s products as the platform.

I could say the same thing about the company that this month’s ThreeWill Hero leads. Unlike ThreeWill and Customware, the company doesn’t focus on software development. Instead, they focus on the business of executing successful mission critical projects. Their medium is a proven process. Their clients they serve are the world’s most successful companies. Their company name is apropos, Project Success, Inc. (or PSI for short). This month we wanted to recognize the company and leader of the company, Clint Padgett.

The Book On Successful Projects

Before we get too far, I just want to point out that Clint actually wrote the book on successful projects. Below is a link to his book on Amazon.com.

How Things Got Started

We started working with PSI long before we “bet the boat” on SharePoint. We worked together to update what they call the Project Success toolkit. This toolkit, which extends what Microsoft Project does as an add-in, helps support the principles of the Project Success Method. There was a lot of time in design spent understanding what was needed to support the process.

Real Partnerships Are Made During Difficult Times

What is perhaps most interesting about the PSI/ThreeWill story is that at one point we came to an impasse. There was a time on the project where both sides decided to stop development. Off the top of my head, I can’t think of another project in our history where we came to such an abrupt stopping point. After a bit of time backing off from the situation, we came together and put together a plan to begin working together again.

This actually helped me mature about what partnering means…going through a difficult time you find out from both sides the intent. Do they walk? Do they come back and look for the way to bring the divide? Do they put the sweat in to make things work or do they just play lip service? This is what you learn during difficult times.

What We’ve Learned About Clint

Tommy shared this with me about Clint and I think it’s spot on:

Clint has been a great client through good times and bad. He is a man of integrity. Because of our long standing partnership and the trust that has been built up we have been able to achieve great things together!

Tommy doesn’t use the word integrity about people lightly. What happens over the course of working together five plus years is you understand the intent of the other party. You find out if they are really interested in a mutually profitable partnership. Clint has been a man of his word and he can be trusted and he we have no doubt that he and his company have many years of continued prosperity. We look forward to working together over the next ten years and beyond.

Huge Shout Out To Crissy Tevis

It’s official, we have found the world’s best product owner. Her name is Crissy Tevis (scroll to midpage). She spends more time at the ThreeWill office than most associates…we love seeing her and we’re thankful that she takes on her role so responsibly. This is another sign of Clint being great leader, he attracts and builds a team of high contributors like Crissy.

Eric Bowden, who has been working closely with Crissy recently, had the following to share:

You couldn’t ask for a better product owner. Crissy is always part of the solution. She is eager to dig into real problem solving and understanding the pros and cons of feature design, while at the same time having vision for the product level roadmap and features.

And every once and a while, she makes sure that Clint does his job…(smile)

A Word From Clint

After hearing he was a ThreeWill Hero, Clint shared the following…

I deeply appreciate being selected as a ThreeWill Hero. My experience with ThreeWill has been nothing short of phenomenal. They are incredibly good at what they do and we reap the benefits during our product development collaboration. I am looking forward to leveraging their SharePoint expertise as we further integrate the Project Success Toolkit with Project Server. By the way, if you’ll send Crissy back to us for a while, I promise to return her before the next phase of development starts!

Clint, thanks again for being a ThreeWill Hero and we look forward to seeing great things from you and your team at PSI…

Learn More About PSI
read more
Danny RyanThreeWill Hero – Clint Padgett

Is your SharePoint like MySpace?

Bo is a Principal Consultant for ThreeWill. He has 18 years of full lifecycle software development experience.

Is your SharePoint like MySpace?

If you are here, then the title did its job. I’ve lured you in so I could get on my soapbox about SharePoint governance. My goal for this post is to focus on aspects of Facebook that I feel contributed to its success and relate them to SharePoint Governance. I am defining success as attracting and retaining users and being the place where they spend more and more time online.

A little history

Over the past several years I, like many people, have witnessed the rise of Facebook and the decline of MySpace. It wasn’t until recently when I saw MySpace purchased for something like one tenth of its previous value, that I stopped to ask more academically, why? Just like millions of people, I was early on the MySpace bandwagon but was turned off by the dizzying array of themes, videos, layouts and essentially chaos I found as I was trying to social network. When Facebook came along, I approached it with some trepidation but knew that social networking was something I wanted to be a part of. Years later, I’m still using it as much as ever.

What are the lessons?

So why has Facebook stuck? Below are a few thoughts on why I feel Facebook has stuck for me. I feel that these lessons can be applied through governance to SharePoint, so it will stick too.

  • Simple Discovery
    • Discovering friends is simple.
    • Potential friends are discovered and pushed as recommendations.
  • Consistent Interface
    • Every friend/fan page is laid out with a consistent look and feel.
    • The most important and relevant content is in the center and related content is around the edges.
  • Personalization
    • Your activity stream is personalized to your needs. If a friend is too chatty, you can hide them; this allows you to keep focused only on items you are interested in.

Why Do I Care?

First, let me say that I’m not using social networking site lessons to suggest building your own corporate social network. Instead, my goal is to show you how they’ve made users stick around, contribute and consume content. If your enterprise is getting social, SharePoint and Jive is a great pairing to achieve both collaboration and socialization.

When it comes to content management and collaboration, two things hold true: content is king and your portal’s usefulness depends on the perceptions of those that use it on a daily basis. It’s easy to get hung up on the rules that govern content. A governance plan should be your organization’s tool to walk the line between two opposite ends of the spectrum. On one end is the Bermuda Triangle where content goes in never to be found again and on the other are so many rules that content never goes in at all.

Applying the lessons to SharePoint

Make no mistake, defining your corporate governance model is a challenge; primarily because there is no one right answer. Business units have differing requirements which change over time, users have diverse goals, and you want to enable and empower but protect at the same time. Let’s take those lessons and dive into areas within SharePoint to consider when creating your governance plan.

Simple Discovery

  • Site Hierarchy (Taxonomy)

One of the first and most overlooked (or over simplified) aspects of discovery in SharePoint is your site structure. Take time to map out areas of content and usage that will map to your web applications, site collections and web sites. Many users are “browsers” and a consistent way for them to navigate is a key to discovery.

  • Site Layout/Structure

When considering your site structure, you must also think about when a user “lands” on a site. If a site is accessible to all users in your company (for example a publicly available HR site), then the layout should be familiar so that sites with similar purpose and visibility are consistent. Having the same items on the quick launch and the same types of views in the main content area is helpful for unfamiliar consumers on a site.

  • Search

Search in SharePoint is an obvious part of discovery. The thing to keep in mind is that your search experience is influenced by many factors. Your site hierarchy, your user security and undoubtedly your use of tagging and metadata all can either help or hurt a user’s search experience.

  • Tagging and Metadata

This may be one of the biggest challenges you will face when walking that line. Your content contributors want quick and simple without requiring lots of metadata and your consumers (especially when searching) expect a lot of metadata in order to help them find what they need. Consider simple Enterprise Keyword columns where users tag and create a folksonomy as a first step, and try to push for more structured Managed Metadata columns as much as feasible.

  • Information Management Policies

One aspect of information management policies that is important is expiration. Explore expiration policies as a way to clean up old documents or move them to more permanent locations when collaboration and usage levels on them are low. If you have successfully added lots of content into SharePoint, there may come a point where there is just too much to consume. A good policy for cleaning up old sites, old libraries and old documents can ensure a better discovery experience.

Consistent Interface

  • Master Pages/Page Layouts

Without a doubt these are very important for creating consistency. If you don’t have specific requirements for your users to customize them, then I would use the same one for all sites and not enable users to change these via SharePoint Designer.

  • Site Templates

Out of the box SharePoint comes with many templates, including a team site which is where many companies start. Explore creating site templates or site definitions for a consistent user experience across sites of the same type. What is part your company’s standard public department site or an enterprise project site is probably different than a standard team site. Site templates start everyone with the same list/document assets to ensure consistency.

  • Navigation

Many times this is an afterthought because it typically doesn’t seem to be a problem until site sprawl has made navigation unusable or unmanageable. Defining your site hierarchy upfront and from the top down will lead to a usable navigation experience. Typically, you should start with top level sites being more open and broadly accessibly and lower sub-sites becoming more specific and tightly controlled.


  • Security

I realize security within personalization seems misplaced, but I’ve put it here to intentionally draw attention to the fact that how you secure your content can affect your user’s experience. More access isn’t always better. Consider using security to prevent unwanted content from clouding your user’s experience. With security trimming for navigation and search, you can reduce the noise that slows users down. Only open up sites as fully public when it makes sense; consider sub-sites for content that is not relevant or that needs to be more secure.

  • Personalized Views

Consider using personalized views as much as possible including those with a [Me] filter where appropriate. Leveraging these as the default views in site templates and on landing pages provides a more meaningful experience to members of the site.

  • Audiences

Make use of audiences, if possible, to target content to users based on role, organization or other specific attributes. You can even use audiences to show navigation items to only specific groups of users.


If you’ve read this blog post all the way to this point, congratulations. I think it means you are serious about creating a governance plan for your organization. While I’ve certainly not hit all aspects that feed into a governance plan, I hope I’ve given you some things to consider when you plan your governance. Check out the related links below to get more prescriptive guidance from Microsoft on SharePoint governance.

Related Links

Governance overview (SharePoint Server 2010) – http://technet.microsoft.com/en-us/library/cc263356.aspx

Governance features (SharePoint Server 2010) – http://technet.microsoft.com/en-us/library/cc262287.aspx

read more
Bo GeorgeIs your SharePoint like MySpace?

SharePoint is like sugar…

Pete is a Director of Technology at ThreeWill. Pete’s primary role is driving the overall technology strategy and roadmap for ThreeWill. Pete also serves as ThreeWill’s Hiring Manager and is constantly looking for new talent to join the ThreeWill family.

The Analogy

SharePoint is like sugar cane juice. What? You don’t get the analogy? Well, neither did I until a few days ago. I personally loved John Underwood’s “SharePoint is like butter” analogy, but I had to capture this one somehow. Just as John said, bear with me, I’ll get there.

The Origin

Over the past 5 years of consulting projects with SharePoint I have had the opportunity to meet some really great people – clients, other consultants and contractors, and even the occasional Java developer. To introduce and discuss SharePoint in general, analogies often are the fastest path to explanation and understanding. On my current project, I have the good fortune of working with a new friend, Neeraj Agrawal.

Neeraj and I were discussing some of the best practices each of us has incorporated over the last several years in SharePoint projects, including analogies to explain the best way to introduce and develop SharePoint based applications, in our experience. I referenced John’s blog post, and mentioned that for ThreeWill engagements we usually try to meet needs with as much of the out of box capabilities as possible before we suggest customization through code.

Neeraj responded with, “SharePoint is like sugar cane juice”. I stood there, motionless, flummoxed. The words hung there, hovering motionless, like a visible, malodorous cloud. After what seemed like minutes, shaking my head in an almost cartoonish fashion, I finally managed, “What?” Neeraj just laughed. And then, he started to explain this jewel. Here’s the abridged version.

First, you have a sugar cane stalk. Fairly obvious.

Next, a sugar cane juice vendor who extracts and sells the juice. The juice vendor sends a stalk through a roller to squeeze out sugar cane juice. Immediately, a customer can now have some juice, no waiting.

The vendor can pass the cane stalk through the press multiple times, and with each pass, another customer gets some juice. Every pass extracts more value of the plant for the vendor, a bit more of the juice, and another happy customer enjoys a glass of sugar cane juice.

There you have it – the perfect SharePoint analogy! Neeraj had just thrown down the best SharePoint analogy ever, short, sweet (literally) and so obscure you are guaranteed to have to explain yourself further.

And here is the explanation of the analogy.

The Explanation

SharePoint 2010 comes out of the box with a large number of powerful and compelling features to address a wide variety of situations. The number and types of situations are too large to describe here, and are explained much better elsewhere. The relevant point here is, with so many features, you can extract value from SharePoint with several passes through the press, there is no need to squeeze too hard on the first pass.

The SharePoint Juice Recipe
  • Endeavor to understand standard features
  • Prototype and implement a basic business process
  • Identify and prioritize the gaps
  • Customize the Most Valuable Gaps First

Endeavor to Understand the Standard Features

First, investigate and understand what SharePoint offers out of the box, and what can be consumed without customization. A word of caution, SharePoint is a HUGE product! As in life, you will more than likely NOT know everything there is to know. This is OK, and should not deter you (the consumer or consultant) from understanding what is available to you at low or no cost of entry. You’ve already paid for SharePoint, or at least the hardware in the case of SharePoint Foundation, why not make the most of your investment.

Learn what site templates come out of the box, and determine if they fit one of your situations closely. In the UI, 20 templates were displayed for me, but there were 51 templates by using Get-SPWebTemplate | Measure. Learn what lists and libraries exist (26 in my environment using Get-SPWeb http:///[rootweb] | % { $_.ListTemplates | Measure}) and what each has to offer. Review the default field types (573 in my environment using Get-SPWeb http:///[rootweb] | % { $_.Fields | Measure}) , their options, limitations, and whether a field already exists that might meet your need. Discover what relationships, references, and interactions you can create between sites, lists, content types ((103 in my environment using Get-SPWeb http:///[rootweb] | % { $_.ContentTypes | Measure}) and more. Finally, learn what web parts are available out of the box for your product SKU and how these can help you without creating your own.

Note: I included the PowerShell cmdlets and counts because, as I was writing this, I was shocked to learn some of these numbers and I learned some new things – even after 5 years.

Prototype and Implement an Initial Solution

After you have spent some time learning what comes out of the box, try putting this knowledge to work. Start by picking a business process that is relatively complex and implement the basic needs of the process. For example, do you track expenses? Try creating an Expense Report “application” using a new site, create a few content types using existing or new site columns, and create some views and web part pages to help display, report and print the expense reports. A list to track the different expense items, expense categories, etc. is a good example that is easy to understand and relatively easy to prototype quickly. You’d be surprised how much can be accomplished for a process like this out of the box.

Be sure to have the correct expectations for this exercise. Don’t look for the limitations, do not assume that this is not good enough, and do not look for excuses to jump to code right away. Accept that the “application” will likely fall short of the mark, but take this as an opportunity to see what is possible. Be creative and try to make things that are acceptable, but not perfect. I think you will be pleasantly surprised at how much of an application like this is achievable, and acceptable, using just what a power user has at their finger tips.

Identify and prioritize the gaps

Now that your first run through the press has extracted a healthy portion of sweet, SharePoint juice, and left your users wondering how they can get more of this magic elixir, it is time to determine what to do the next. Let’s take our Expense Report application again. Users liked the idea of an online Expense Report app, but the simple lists with only some content types and views fall short. Management wants a custom workflow, since what you tried initially with the approval wasn’t enough. Users want a way to track expenses offline and then upload them. And, the finance users want a simple way to track and manage payments and some views that show them expenses that are not possible with simple list views.

Now we have enough for a second run through the press to extract some more sweetness. Can you still stay away from code? Maybe. There’s still more juice to be had without squeezing too hard. Maybe a workflow modified in SharePoint Designer 2010 will fit the bill for the managers. No custom code yet, and they might be willing to accept this. Next, you might be able to meet the user’s needs by using InfoPath 2010 or SharePoint Workspace 2010, or by getting even more creative with Excel or other options. Finally, perhaps a third list, secured to only finance users, will enable them to track the payments and a content query web part might provide them with the views they want.

These may work, but what happens when you need to squeeze even harder?

Customize the Most Valuable Gaps First

Finally, once you have exhausted the features you endeavored to learn, start customizing with the new requirements that present the most value by addressing the biggest gaps. The finance team would love to have a more specific UI for their purposes, but they are fine with a list that only they can see and manage. The managers are happy with the new workflow that lets them approve and escalate approvals as needed. But, the users really need a better alternative to the processing of offline expense items.

Since the users at this point are the ones with the most compelling or urgent need for customization, you can now determine a viable alternative for them. You can spend time getting deeper into requirements and scenarios to understand the best way to address the needs, all while the finance team, managers and most users have a viable, functional alternative to managing expenses and are getting reimbursed.

Some Final Thoughts

Think about how you develop solutions today. If your organization immediately moves to gathering and defining deep, fine grained requirements that are intended to ensure every desire of the users is met, then SharePoint may present some mental challenges for you. Developing in SharePoint, and extracting value immediately is a huge advantage that SharePoint as an application itself provides.

Finally, Neeraj did offer a different spin to this crazy analogy. Here it is in summary. First, treat SharePoint like an application and learn to use all of the features it gives you. Once you have learned the features, and mastered it’s capabilities, treat it like a platform and build your own features that exploit the platform to its fullest. Finally, exploit the API of the platform and create your own solutions by connecting, building or extending the platform.

Thanks Neeraj for helping me add another sweet SharePoint analogy to my bag of tricks and for helping me make Mr. Underwood a little happier this week!

read more
Pete SkellySharePoint is like sugar…

SharePoint is like butter…

John Underwood is a Technical Evangelist at ThreeWill. He has nearly thirty years of software development experience. He is an experienced technical instructor with superior presentation skills and is proficient in delivering standard curriculum as well as developing and delivering custom curriculum.

SharePoint is like butter…

I love Paula Deen. There. I said it.

(I know that food snobs and cardiologists everywhere are recoiling in horror.)

I love Paula’s accent and the way it reminds me of my many aunts as I was growing up. I love her commitment to cooking with butter. I love the way she makes everything sound so yummy on her cooking show.

What, you may ask, does that have to do with hiring a SharePoint expert?

Well, bear with me and eventually we’ll get there…

Before she became a big Food Network star Paula got her start on a show called Doorknock Dinners. The premise was that the host (Gordon Elliot) would take a chef, show up unannounced at the door of a busy person, and offer to cook dinner using only items they had in the house.

I read a blog post recently about the rising demand for SharePoint experts (seeing that I just started at a company that specializes in SharePoint development, I was pretty excited about this news). This article made the case that good SharePoint solutions are based as much as possible on using existing SharePoint functionality. This mirrors my experience here at ThreeWill. I was taught early on that we always look to meet a customer’s need using SharePoint’s built-in capabilities, and we resort to custom code only when those facilities don’t meet the need at hand.

Based on the above I would say that being a SharePoint expert is similar to Paula Deen’s experience on Doorknock Dinners in this respect: as much as possible you want to cook with the ingredients that are already there.

As a developer of nearly 30 years and as someone that’s spent the last decade building ASP .NET web applications, I have to confess that whenever a business problem arises my first impulse is to open Visual Studio and start writing some code. As I began to learn more about SharePoint 2010, I was excited to learn about the tight Visual Studio 2010 integration, including the ability to press F5 and instantly get build, deploy, and debug capabilities. However, as familiar and comfortable as that coding model is for me, the reality is that should be a last (or at least later) resort. Good SharePoint solutions take full advantage of the lists, libraries, workflows, and other capabilities that are already baked into SharePoint before resorting to custom code. Doing so will result in some big paybacks, including:

  • Shorter delivery time
  • Easier application support story for an IT staff that’s already supporting SharePoint
  • Better upgrade path to future releases of SharePoint

You’ve probably heard the medical school maxim “first, do no harm.” A SharePoint expert might consider adopting the maxim “first, write no code (until it is absolutely necessary)”.

If you’re looking to hire a SharePoint expert – be it an individual, or a firm such as ThreeWill – look for someone that is willing to go as far as possible with what SharePoint offers out of the box (…and don’t forget to tune in to Paula’s Home Cooking on the Food Network to see all those yummy recipes).

read more
John UnderwoodSharePoint is like butter…