Sunday, March 10, 2013

How to display all social comments and bypass Social Security Trimming

If you have worked with the Noteboard web part before then you know that you will need SharePoint search as a lot of Social features use social security trimming. Recently I was building an intranet where I needed to display all social comments regardless of the social security trimming. It happens that the Social Comment Manager actually supports a method which is private but has a parameter for ignoring the trimming. By using reflector I was able to load all the comments and display them as part of the feedback of a publishing page.

Below I will show you the method I have used to display all social comments using reflection (click on the image to get a better view). Thanks to Emile from Rubicon for the final touch here!



iOS Game Starter Kit available!

Most of the readers of my SharePoint blog know that I have another hobby which is game development. Last week I have released an iOS Game Starter Kit for anyone who is considering to try developing a game himself.


I have released an iOS game starter kit called Meet the Masters on the Unity Asset Store for only $65 dollar. It literally contains the full game released on the Apple App Store last year including:


  • 36 scenes
  • music & FX
  • use of particles
  • use of in app purchases
  • save & load
  • score
  • game center integration
  • in between scenes
  • use of physics
  • use of particles
  • use of 2D and 3D fonts
  • use of custom GUI skin
  • taking into account iPhone, iPad & resolution differences
  • use of collectibles
  • etc etc
Where other starter kits are either incomplete games or on the hand become too complex, this kit really kicks ass as the scripts are compact and easy to read. Everyone who is considering should definitely buy this one:


Thursday, January 17, 2013

How to quickly create test content for a publishing site

In this post I will describe how to create SharePoint publishing pages including images by using any RSS 2.0 feed. This includes parsing the feed, downloading linked images, creating SharePoint pages and associated list items, uploading images to library and setting all of the values. I have chosen to build a console application in C# for demonstration purposes.

Why is this useful?

In any project where you are packaging new content types and page layouts for a publishing site, you will need to test the solution which requires you to create pages and fill in all of the values. If you are rolling up content you will even need to create a number of pages. This is a manual process which becomes time consuming over time. Especially if you need to attach images as well.
Secondly, creating pages yourself means you have to enter content which could be of course a Lorum Ipsum generated piece of text but would that be a valid test case?
In this post we will parse a RSS feed and translate that automatically into SharePoint Publishing pages. If the feed has enclosed image links we will download the image and store it in a SharePoint image library so that we are able to use it on the page as well. This will safe you a lot of time and the RSS feed will generate different content over time.

The feed

In this post we will use the news site NU.NL which is the most popular news site in the Netherlands. The news can be consumed through a public news feed where you can select a certain news category or filter through a tag. 
In the example we will filter the news using a tag. The format of the RSS feed URL would be something like http://www.nu.nl/feeds/rss/tag/microsoft.rss if we would like to get articles about Microsoft.

Parsing the RSS feed in C#

RSS 2.0 is a standard which you can parse in C# as a SyndicationFeed. Any article would be a SyndicationItem. Both classes are part of the System.ServiceModel.Syndication namespace.
The first step is to create a XmlTextReader and open the reader using:
XmlTextReader MyReader = new XmlTextReader(feedURL)
Secondly we would be reading the feed by loading the feed using the MyReader:
SyndicationFeed MyFeed = SyndicationFeed.Load(MyReader)
When you want to parse each item in the feed and create a publishing page for each item, you create a loop like this:
            using (site = new SPSite(SiteURL))
            {
                using (web = site.OpenWeb())
                {
                    pubWeb = PublishingWeb.GetPublishingWeb(web);
                    foreach (SyndicationItem myItem in MyFeed.Items)
                    {
                       // grab images and create page
                                         }
                    pubWeb.Close();
                }
            }
Each item has certain properties like Title and Summary according to the RSS specifications.

Downloading the image 

Before we create a publishing page, I would like to download the image for the article and upload to a SharePoint library. The reasons that I am doing that is that I don't want to refer to images on the web. Instead I want to rely on images that are stored in my SharePoint libraries. Of course, using images from your local libraries perform a lot better when displaying images that are pulled from the web every time you show a page.

Downloading the images means that I have to grab the image link for the RSS item and next stream the image to disk.The link to the image is stored as an associated link URI. To get just the filename I use the following reliable syntax (which trims everything up to the filename):
System.IO.Path.GetFileName(myItem.Links[1].Uri.LocalPath)
To download the image to a local directory I use the following code:
        static void CacheImage(Uri uri, string fileName)
        {
            WebRequest request = WebRequest.Create(uri);
            request.PreAuthenticate = true;
            // If you need to authenticate through proxy 
            //WebProxy proxy = new WebProxy("");
            //NetworkCredential cred = new NetworkCredential("******", "******");
            //proxy.Credentials = cred;
            //request.Proxy = proxy;
            WebResponse response = request.GetResponse();
            Stream responseStream = response.GetResponseStream();
            CopyStreamToFile(responseStream, fileName);
            UploadFile(fileName);
        }
 
        static void CopyStreamToFile(Stream stream, string targetFile)
        {
            const int BUFFER_SIZE = 1024;
            FileStream file = File.Create(ImagesDir + targetFile);
            byte[] buffer = new byte[BUFFER_SIZE];
            int read = 1;
            while (read > 0)
            {
                read = stream.Read(buffer, 0, BUFFER_SIZE);
                file.Write(buffer, 0, read);
            }
            file.Flush();
            file.Close();
        }

Uploading the image to a SharePoint image library

The next step is to upload the image to a SharePoint image library. For that purpose I use the following code:
        static void UploadFile(string fileName)
        {
            FileStream fs= File.OpenRead(ImagesDir + fileName);
            byte[] FileContent= new byte[fs.Length];
            fs.Read(FileContent, 0, Convert.ToInt32(fs.Length));
            fs.Close();
            SPList DocLib = web.GetList(SiteURL + "/" + ImagesLibraryName);
            web.Files.Add(DocLib.RootFolder + "/" + fileName, FileContent, true);
        }

Adding the RSS item as a publishing page

So right now, we have the image associated with the RSS item stored in our Images library on SharePoint. The next thing is to create a publishing page and copy all of the RSS item content to the pages list item including a reference to our image.
First of all our publishing page is based on a certain page layout and content type. In the code below I assume you have stored the names of those in two variables. To be on the safe side I first grab all page layouts that are bound to a specific content type and select the one I need. Of course, that can be done quicker but it just to give you a better understanding of how that works. So first our helper function:
        static PageLayout GetPageLayout()
        {
            PublishingSite pubSite = new PublishingSite(site);
            SPContentType contentType = pubSite.ContentTypes[MyContentType];
            PageLayoutCollection pageLayouts = pubSite.GetPageLayouts(contentType, true);
            Dictionary dPageLayouts = new Dictionary();
            foreach (PageLayout pageLayout in pageLayouts)
            {
                dPageLayouts.Add(pageLayout.Name, pageLayout);
            }
            PageLayout pageLayoutToUse = dPageLayouts[MyPageLayout];
            return pageLayoutToUse;
        }
All right, we have the PageLayout show how to I create a new publishing page? Here is an example:

       static void AddPage(SyndicationItem MyItem)
        {
            string pageName = MyItem.Title.Text + ".aspx";
            // Check if page does not exist already
            SPQuery query = new SPQuery();
            query.Query = "" + pageName + "";
            PublishingPageCollection pages = pubWeb.GetPublishingPages(query);
            if (pages.Count == 0)
            {
                // Add page
                PublishingPage newPubPage = pubWeb.GetPublishingPages().Add(pageName, GetPageLayout());
                // Add page list item
                SPListItem newPage = newPubPage.ListItem;
                SPList PagesLibrary = newPage.ParentList;
                newPage["Title"] = MyItem.Title.Text;
                newPage["Page Content"] = Microsoft.SharePoint.Utilities.SPEncode.HtmlDecode(MyItem.Summary.Text);
                
                Microsoft.SharePoint.Publishing.Fields.ImageFieldValue MyImage = new Microsoft.SharePoint.Publishing.Fields.ImageFieldValue();
                MyImage.ImageUrl = (SiteURL + "/" + ImagesLibraryName + "/" + System.IO.Path.GetFileName(MyItem.Links[1].Uri.LocalPath));
                newPage["PublishingRollupImage"] = MyImage;
                newPage.Update();
                newPage.File.CheckIn("");
                newPage.File.Publish("Published on creation");
                newPage.File.Approve("Approved on creation");
            }
        } 
How does it work? First we will determine the name of our page (which will be shown in the URL). I am using the title of the page for that. Next, I will check if the page does not already exist. Can be done quicker as well. ;-) Next I create the publishing page by calling the Add function where I need to provide the page name and page layout. This is where we use our helper function. Next, we will look up the associated list item of the page in order to set the content fields. In the example above I will set the title and page content fields. Also, I set the link pointing to our freshly uploaded image as well. Here it is important that the Rollup image is not a string field but an ImageFieldValue object. SharePoint builds the image HTML tag out of a number of properties of the ImageFieldValue object like width, height etc. Finally we update and check in the page. Keep in mind that I did not include error handling so if your library does not have check out enabled or approval for instance you may ommit these things.

And that is it!

Summary

A RSS 2.0 feed can be parsed in C# using a syndicationfeed which contains syndication items. If an item contains a link to a picture we can download the image to our local drive and upload them to a SharePoint images library. Next we are able to create a publishing page using a page name and page layout associated with a content type. Finally we set our content, including a link to our uploaded image, by setting the list properties and especially our ImageFieldValue object.

Download complete source

Why not. Download the complete source here: 

And have fun!