Tuesday, October 22, 2013

Stop Building Custom Web Parts in SharePoint, Use the XML Viewer Web Part Instead!

With the rise of SharePoint 2013 and Apps for SharePoint, client side object model (CSOM) and JavaScript object model (JSOM) are becoming the norm for development on SharePoint.  In SharePoint 2013 the CSOM and JSOM object models have been greatly expanded and optimized making client side development a joy.  Even in SharePoint 2010, these object models allowed for a lot of development opportunities.  If you needed something more robust, you could very easily deploy a WCF web service and make AJAX calls to the server.

With this thinking in mind, we can stop building custom web parts which are deployed to the server and instead build functionality using JSOM and the out of the box XML View web part.  Let's take a look at how to accomplish this.

The complete code for this post can be downloaded from the TechNet Gallery here.

There are only a few components to this:
  • XML Viewer Web Part - This is the OOTB XML View web part that comes with SharePoint.
  • XML File - This is a standard XML file that contains HTML markup that will be rendered in the XML Viewer web part.
  • JavaScript File - This is a standard JavaScript file with which to make JSOM and/or jQuery calls from.
  • CSS File - A standard CSS file to applying styling to your HTML.
To start off, we'll create a new document library to hold our XML and later CSS and JavaScript files.  For this demo it will be a generic document library called "XmlWebParts".

Inside this library I've created a folder to hold the first demo files.  Inside the folder is an XML file titled "HelloWorld.xml".

This is a simple XML file that only contains HTML markup.  The markup is very simple and only contains two DIVs and a Hello World statement, some formatting, and another line of text.
<div>Hello <strong>World!</strong> </div> <div> This is another DIV. </div>

Now that we have that, we can create a new blank site page, and add an XML Viewer web part to it.  Opening the properties pane of the web part, we only need to set the "XML Link" property to point to our new XML file.

In this example the file lives at "/sites/blogexamples/XmlWebParts/HelloWorld/HelloWorld.xml", so this is the path placed into the "XML Link" property.  Saving this and checking in the page results in the HTML content from the XML file being displayed in the web part.

Now obviously this demo is pretty simple and not "real world" by any means.  So, let's translate this into something real world.  Let's say your manager has asked you to develop a web part (SharePoint 2013) for the SharePoint homepage which has the following requirements:
  • Web part must display information for the current user logged in from their user profile and social feeds.
  • Web part must display a welcome message to the user above their user profile picture.
  • Under the welcome message and profile picture, the web part must display any items the user is following, along with a link to that item for easy access.
We can easily produce this web part using HTML, jQuery, JSOM, and an XML Viewer web part.  First let's start with building out the files needed for this web part.  We'll create another folder in our document library called "UserWelcome".

Inside that folder we'll place an XML file and a JavaScript file.

Now we have two files, an XML file for our HTML markup and a JavaScript file.  Let's take a look at the HTML markup in the XML file.

Image below to account for horrible formatting of code!
<script type="text/javascript" src="http://code.jquery.com/jquery-1.10.1.min.js"></script> <script type="text/javascript" src="/_layouts/15/sp.runtime.js"></script> <script type="text/javascript" src="/_layouts/15/sp.js"></script> <script type="text/javascript" src="/_layouts/15/sp.userprofiles.js"></script> <script type="text/javascript" src="/sites/blogexamples/XmlWebParts/UserWelcome/UserWelcome.js"></script> <div id="WelcomeMessage"> Welcome back <span id="WelcomeMessageUserName"></span> </div> <div id="UserProfilePicture"> <img id="UserProfileImage" /> </div> <div id="UserFollows"> </div>

In this markup, the first thing we do is reference jQuery from a CDN, then we load in some specific SharePoint JavaScript files needed to pull user profile data.  Finally we reference the UserWelcome.js file we uploaded.  As you can see, the HTML is very minimal and only includes a few DIVs and an image placeholder.  All the content will be loaded from the JavaScript file.  Let's take a look at that.

Image below to account for horrible formatting of code!
//<![CDATA[ $(function () { // Don't fire function until sp.userprofiles.js is loaded ExecuteOrDelayUntilScriptLoaded(getUserProfileProperties, "sp.userprofiles.js"); }); // Get the user properties for the current user function getUserProfileProperties() { // Create a client context var clientContext = new SP.ClientContext.get_current(); // Get the People Manager and the current user properties var peopleManager = new SP.UserProfiles.PeopleManager(clientContext); userProperties = peopleManager.getMyProperties(); clientContext.load(userProperties); // Get the following Manager and the items the user is following var followingManager = new SP.Social.SocialFollowingManager(clientContext); following = followingManager.getFollowed(15); // Execute the query clientContext.executeQueryAsync(onSuccess, onFailure); } // Process the results and populate a DIV function onSuccess() { $("#WelcomeMessageUserName").text(userProperties.get_displayName()); $("#UserProfileImage").attr("src",userProperties.get_pictureUrl()); var followedItems = "Items you are following:<br />"; $.each(following, function( index, value ) { followedItems += "<a href='" + value.get_uri() + "'>" + value.get_name() + "</a><br />"; }); $("#UserFollows").append(followedItems); } function onFailure() { alert("Error occurred retrieving user profile information."); } //]]>

NOTE: The scripts are wrapped in a CDATA container in order to make them render and function properly.  In my experience sometimes you do not need this, but it never hurts to have it there.

This is where all the work takes place.  There is one major function here called "getUserProfileProperties()" which is called using the ExecuteOrDelayUntilScriptLoaded function built into SharePoint.  Basically we will be accessing user profile information, so we need to make sure the sp.userprofiles.js file is loaded first.

This function simply creates a PeopleManager object and calls the getMyProperties() method to retrieve all the user profile properties for the current user.  Then it creates a SocialFollowingManger object and calls the getFollowed() method to pull all the items the user is following.  If you look at the code the method call includes an INT which indicates which type of SocialActors we want to retrieve using the SocialActorTypes enumeration.  For instance, Users, Documents, Sites, etc.  15 indicates we want all SocialActors to be returned.  For more info on the SocialActorTypes click here.

If all goes well the onSuccess() function is fired and the user profile properties and following information will be populated in the DIVs in the HTML, as shown below.

Bam!  Not too bad, but its basically just some data without any formatting.  Let's add some CSS to pretty it up.  We'll add a CSS file to the UserWelcome library and call it UserWelcome.css.

Since we gave all of our HTML elements IDs, targeting them with some CSS is quite easy.  The following code is added to our CSS file.

#WelcomeMessage {
    float: left;
    padding-right: 6px;
#WelcomeMessageUserName {
    font-weight: bold;
#UserProfilePicture {
#UserProfileImage {
    border: solid 1px #C0C0C0;
#UserFollows {
    border:dashed 1px #C0C0C0;
    padding: 6px;

Finally, we'll update the UserWelcome.xml file to include a reference to the CSS file with the following line:

<link rel="stylesheet" type="text/css" href="/sites/blogexamples/XmlWebParts/UserWelcome/UserWelcome.css"/>

With the CSS added, our web part has some simple styling in place to make it a little more presentable (and I mean just a little more)!

And there you go!  A simple demonstration using HTML, JavaScript, JSOM, and the XML Viewer web part to create a "custom" web part for your users.

Using this approach has several advantages:
  • It allows for non-C#/Visual Studio development to take place
  • It allows for users with only HTML and JavaScript experience to create rich web parts without the need for server side code
  • It allows for easy maintenance and upgrades since all the code is stored in a standard document library
  • It utilizes JSOM for building web parts, which is a best practice in 2013 (also CSOM)
  • You can utilize versioning in the library to ensure new updates that may break functionality can be easily rolled back
This of course is not a one size fits all solution, as there will certainly be times you need server side code.  However with the expansion of the CSOM/JSOM functionality in SharePoint 2013, many development opportunities can be explored in this fashion.  It also makes a great development model for Office 365 as well.

The complete code for this post can be downloaded from the TechNet Gallery here.



  1. This comment has been removed by the author.

  2. Hi Brandon,

    Nice post, which gives a detailed step-by-step instruction. One remark though. In 'UserWelcome.js' you use the folllowing line to create a client context:

    var clientContext = new SP.ClientContext.get_current();

    AFAIK 'new' is not necessary. The use of 'new' indicates that the function that is called (get_current) is treated as a constructor. This means that the runtime passes a new empty object to the function, which can augment the object through 'this'. The passed object is returned automatically at the end of the function (unless the function returns another object explicitly).

    If you look at the source of get_current, you'll see that this function itself creates and returns a ClientContent object based on the relative URL of the page. The fact that the name of get_current doesn't start with a capital letter (a convention in JavaScript) also indicates that this is not a constructor function. So IMHO there is no need for a passed object and the use of 'new'.