The Method of SharePoint, a study in SharePointology

In this blog post I will dig deep into the many faces of SharePoint, not just from a technology perspective, but more so from its softer side, the conceptual side, the approach, the method of its reach, and much more. I’ll call it SharePointology; A term I thought I can first introduce here on this blog, but as it turns out, someone else has it. Man! Gosh! Darn it!. Not a problem at all I say. This is just amazing. Anyways, we keep going.


SharePoint, as a technology, offers organizations and their employees an opportunity to connect with one another, communicate and collaborate on teams, manage and define their data, locate and personalize their content, automate their processes and as a result make better business decisions. It doesn’t stop there. SharePoint goes out the door connecting you with your customers. And today, all of that is available to the enterprise. With SharePoint 2010, Microsoft is reaching high grounds. Not a surprise to anyone in this field. With every new version, a new experience we shall have and a new way of doing things.

SharePoint 2010 is The Business Collaboration Platform for the Enterprise and the Web. It has many features from creating sites and team workspaces for both internal and external consumption to automating business processes and integrated data and reporting capabilities. More and more you’ll find as you dig deeper and deeper into the platform.

Now, having been involved on many SharePoint-related projects, I’ve noticed a trend in the product. We’ve seen some new and amazing features come online and we’ve seen some old ones stay afloat. We’ve seen some features that still have the same issues and some new ones with a whole set of their own problems. Few come to mind; HTML rendering still a mess even though there is a much better focus on usability and accessibility. Navigation Inheritance from one Site Collection to the next still an issue. Personalization Links for My Sites, etc.

So, what’s the matter you think? Where are we doing with this? Here are few of my observations that will hopefully shed some light onto the conversation; I call them collectively, The Method of SharePoint. Well, of Microsoft.

Please note: anything you read here is my own opinion with a sliver of insight and creativity Smile yeah, ok now.

The Method of SharePoint

Reach – Go wide then deep. A simple approach to cover more ground. In a SharePoint sense, add features then improve on existing ones. SharePoint has always been called the “Swiss Army Knife” of collaboration software. It has a wide range of features from content management capabilities to reporting and process automation. In the professional services world, there’s always this question: Go for large-size projects less volume per year or reach more customers and increase your pipeline, but deliver small? Which one is good for you? I don’t know. SharePoint seems, at least from my opinion, to go for the features and increase its reach. SharePoint is not and I don’t think it will be in the short term, The Enterprise Content Management platform around. Unlike some vendors out there, SharePoint is still missing some depth when it comes to Records Management and Content Management. Deep auditing and workflow capabilities still missing. We’re still faced with the same problems and nothing has changed in the solution. Ask some SharePoint Administrators. Yes, in SharePoint 2010 we have better auditing and monitoring capabilities, but we still don’t know the answer to who has access to what question. We’re dependent on third party vendors to fill in the gap. This brings me to my second observation.

Fill in the Blank, Third Party Heaven –  Do a BING on the phrase “SharePoint” and come back and let me know what you find. Thousands and thousands of pages producing technical content, videos and training material, blogs and newsletters, off-the-shelf software products to fill every gab, full life cycle management systems built for SharePoint, 3rd party vendors upon 3rd party vendors, community and open source projects, etc. etc. etc. SharePoint this and SharePoint that. Everybody wants SharePoint and we’ve been competing on who can come up with the next SharePoint plug in or adapter or web part or middle-tier product to complement what SharePoint Out-Of-the-Box (OOB) offers. You can say whatever you want; product team missed this or they didn’t figure this out or that out, etc. I say, Microsoft is smarter than all of us. If you want to stay around, you don’t build a complete package. You give your customers what they need at the moment and what they can handle. You buy time. You build a market around the product. For us developers, we love to write components that show up somewhere. We love to integrate. And that’s what we have with SharePoint. A fill in the blank policy written for developers meant for the business.

Market Induction – Oh well, here we go. Let’s build a product, a great product with a great vision and call it SharePoint. Then, lets’ build a product that breaks the product we just created. Let’s call this one SharePoint Designer. Great idea. Offer and promote product features to a wide range of users; Average, Power User, and Site Administrators. Don’t forget the Farm Administrators though, SharePoint 2010 offers a plethora of monitoring, reporting and control features to make sure things don’t get out of hand. We will also add this throttling feature to BCS and Lists and such, but allow the developer to override it. Nice I say. Actually very good. See, what’s happening here is an execution of a strategy to keep the ball moving forward and not in just one direction, but in many directions. Microsoft doesn’t just think of the business and the business user (power to the people), they think of us technical folks also. Everybody has something to do and work on and no one gets tired. The market grows in many directions. Imagine SharePoint is here and there is no way to extend its functionality, modify it, configure it, or do anything with it except through a single interface or tool. Imagine this for a second and you’ll see what I mean. It’s all about balance. I give you something 50%, you get excited, you hire me, I code the other 50%. We’re both happy.

From the horizontal to the vertical – Pretty soon, SharePoint itself will become it. A single unit of work and feature set. It will mature enough to start driving deeper, going vertical into .NET; its underlying power house. Pretty soon things we needed code for will be able to do without a line of code. Example: Visual Web Part, Visio Workflows, etc. SharePoint will become the transportation system on which our work travels. Things will become simpler and simpler as technology advances and SharePoint adapts. SharePoint will drive more into .NET than it has ever driven. Notice this version, V4 (2010). REST got introduced. WCF got introduced. JQUERY got introduced, Client Object Model (managed and ECMA or JavaScript) got introduced. I am hoping MVC get’s in there as well. All of this should make you think about the direction here. I’ll summarize it for you:

  • More into the .NET platform for consistency, simplicity, converting people from pure .NET to SharePoint developers and back and forth
  • Back to the 1990’s with more support for client side scripting. Better user experience now we’ve got the tools with Ajax Support and SOA models

Pretty soon, the horizontal goes vertical, matures, finds more common ground and genericise its features.


Looks like this post is growing out of hand and I need to close it down here. I’ve enjoyed writing this post and I hope you find it interesting. I’ll try to break some of this down and organize it better next time around. Till then, think of SharePoint more than you do today. Look at its angles and ask yourself why is it like this. Hopefully you’ll figure out where its heading next.

Take it easy.

Posted in SharePointology | Tagged

SharePoint can TXT while it drives – Configure SMS Text Messaging for SharePoint 2010

While for us, in some States, to TXT when driving is to break the law, SharePoint 2010 can do it while it drives and behind the scenes legally.

See, in addition to sending Alerts via Outbound Email Servers using the SMTP protocol, SharePoint 2010 can send you TXT messages using Short Message Service or SMS. This is one of the many new features in SharePoint 2010 that means so much to this generation Smile. Did you say SharePoint can TXT me now! Wow. Now, that’s something. A while back I wrote a post on how SharePoint is adapting to our social behavior; well, this one is an example.

Let’s get to it. To configure this new feature, access the Central Administration site and click on the System Settings group hyperlink. On that page, you’ll see a Configure Mobile Account link. This configuration page is also available from the Application Management page and can be applied per web application.


Now before we go ahead and configure this feature, you will first need to create an account with one of the SMS Service Providers out there. I can’t say any provider will do, because I really don’t know much about them or what exactly they offer. The most important piece of information you need is their SMS Service URL and if it is serviced over SSL or not. Depending on where you live and your mobile phone provider is, you may have a different URL for the service. It turns out that the URL used to configure this must be based off of Microsoft’s own Office Mobile Service protocol. This protocol is explain in more details here on MSDN.

Step-01 – Create an Account

Click on the Configure Mobile Account link. You will see in the description a link to a page leading to some of the Service Providers in your area. You’ll have to choose your Country and your mobile phone network provider.


I initially created an account with MessageMedia. They offer several APIs for their service. It wasn’t exactly what I was looking for. Before I found out I need a OMS URL, I figured it may be a simple REST or ASMX service, but that didn’t go. So I went ahead and registered for SMS Officer. SMS Officer sent me a confirmation email message with an OMS URL in it. This is what we want. In addition, SMS Officer will send you a confirmation code via SMS to your phone.


Record the Service Provider URL, the User ID and the Password. These values is what we’ll use to configure the SMS feature.

How did I know that I need an OMS URL? When a did a quick BING on the subject, I landed on this training video from TechNet. At the same time, I found this article as well.

Step-02 – Download and Install the SSL Certificate

Now, go ahead and access the URL provided to you. Notice, its serviced over SSL. Go ahead and download the SSL Certificate. There are at least a couple of ways to do that.


You can save the certificate on your machine and name it as you wish.


Now that you’ve downloaded the certificate, we will need to install it on our SharePoint 2010 server. We’ll use PowerShell to do that. The key here is to use the Root Certificate Path as the name. PowerShell commands and explanation on them can be found here on TechNet.


After you run the above PowerShell commands, you should see something like this.

USERTrust Certifacte Info Message

Step-03 – Configure the SMS Messaging feature

Now, lets configure. Go ahead and enter the URL, your User ID and Password into the Configure Mobile Account page. Click on Test Service button to validate your configuration.


And after validating your settings, you should see something like this.


Step 04 – Configure Alerts

Now,  you’re ready to configure your own Alerts if you like and get ready to receive them via SMS. To configure Alerts, at least for testing, choose any of your SharePoint lists or libraries and access its default page (Usually, the default View ASPX page). Under List/Library Tools, Click on the Alert Me Ribbon Action. You’ll see a checkbox there to enable SMS Messages. Include your mobile phone number and check the box and hit OK. I forgot to take a screen of that page, sorry. My server is shutdown for the night Smile

Now, that you’ve configured an Alert. Go ahead and create a new Item or Upload a Document if you’re on a library. Cross your fingers and wait for the TXT message to appear. For me it was quick.


Step 05 – Receive your SMS Alert

I received my SMS TXT right away here. I took a picture of my BlackBerry Storm screen showing the Alert.



Finally, overall, the entire experience took about an hour to complete. I’m a bit slow some may say Smile

That’s it for now.

Take it easy!

Posted in SharePoint Administration | Tagged

Setting Up a Custom Event Log Installer with InstallUtil.exe and SharePoint 2010 Feature Receiver


If you’ve seen this error message before “The source was not found, but some or all event logs could not be searched. Inaccessible logs: Security.”, you’ll know what I’m taking about. If not, that’s cool. In this blog post, I’ll attempt to show you how to setup a custom Log and have it display in the Windows Event Viewer.

I will break this down to several sections.

Scenario – The reason behind doing this is simple. You want to write to the Windows Event Log from inside of your custom application and you like to follow best practices and be nice about it 🙂 This application can be a Windows Forms application or simply another Web Application or even a custom application living inside of SharePoint. Since my focus been on SharePoint these past few years, I’ll focus on the latter type of application.

Setup – Here’s what I’m going to have. I will create me a SharePoint 2010 Empty project in Visual Studio 2010 deployable in a Farm. I will add a reference to System.Configuration.Install. I will then create a class that inherits from System.Configuration.Install.Installer, place the RunInstallerAttribute on top of it, write few lines of code there. Then I will create a Feature with an event receiver that will eventually run the InstallUtil.exe executable and create the Event Log with its Source for me. To store my installer logs, I’ll create a folder on my C Drive and call it JMH.


Solution  – Here, I’ve got several parts.

01. CustomInstaller.cs – This is a simple .CS file inside of my project. I added few references to it. System.Configuration.Install, System.ComponentModel, and System.Diagnostics. Here’s the code for it. I removed unused Using statements.

   1: using System.ComponentModel;


   3: using System.Configuration.Install;

   4: using System.Diagnostics;


   6: namespace JMH.SharePoint.CustomInstaller

   7: {

   8:     /// <summary>

   9:     /// Run InstallUtil tool. Can be found here: C:\Windows\Microsoft.NET\Framework64\v2.0.50727

  10:     /// installutil /LogFile=C:\JMH\EventLogCustomInstaller.InstallLog /AssemblyName "JMH.SharePoint.CustomInstaller"

  11:     /// 

  12:     /// Ref1.

  13:     /// Ref2.

  14:     /// </summary>

  15:     [RunInstallerAttribute(true)]

  16:     public class EventLogCustomInstaller : Installer

  17:     {

  18:         private EventLogInstaller _EventLogCustomInstaller;


  20:         public EventLogCustomInstaller()

  21:         {

  22:             // Create an instance of an EventLogInstaller.

  23:             _EventLogCustomInstaller = new EventLogInstaller();


  25:             // Set the source name of the event log.

  26:             _EventLogCustomInstaller.Source = "JMH";


  28:             // Set the event log that the source writes entries to.

  29:             _EventLogCustomInstaller.Log = "JMH";


  31:             // Add myEventLogInstaller to the Installer collection.

  32:             Installers.Add(_EventLogCustomInstaller);

  33:         }


  35:         public static void Main()

  36:         {

  37:         }

  38:     }

  39: }

02. JMHCustomInstaller.feature – This is a new Feature I created in my project. The scope is set to Web by default on this. I’ll set Activate On Default to False and Always Force Install to True.

03. JMHCustomInstaller Event Receiver – I added an event receiver to this feature. I removed all the overrides from the class except for the FeatureActivated event. I’d like to use this to initiate the InstallUtil.exe process and create my custom event log. I added few using statements as well: System.Diagnostics, and System.IO. I also changed the namespace. The code is as follows.

   1: using System;

   2: using System.Runtime.InteropServices;

   3: using Microsoft.SharePoint;


   5: using System.Diagnostics;

   6: using System.IO;


   8: namespace JMH.SharePoint.CustomInstaller

   9: {

  10:     /// <summary>

  11:     /// This class handles events raised during feature activation, deactivation, installation, uninstallation, and upgrade.

  12:     /// </summary>

  13:     /// <remarks>

  14:     /// The GUID attached to this class may be used during packaging and should not be modified.

  15:     /// </remarks>


  17:     [Guid("9c9942de-e851-427f-82d0-5c519e7a7058")]

  18:     public class JMHCustomInstallerEventReceiver : SPFeatureReceiver

  19:     {

  20:         public override void FeatureActivated(SPFeatureReceiverProperties properties)

  21:         {

  22:             //  Do some clean up

  23:             try

  24:             {

  25:                 if (EventLog.SourceExists("JMH"))

  26:                     EventLog.DeleteEventSource("JMH");


  28:                 if (EventLog.Exists("JMH"))

  29:                     EventLog.Delete("JMH");

  30:             }

  31:             catch (Exception)

  32:             {

  33:             }


  35:             //  Give it a try

  36:             try

  37:             {

  38:                 string installerArguments = String.Format("/LogFile={0} /AssemblyName {1}", @"C:\JMH\JMHCustomInstaller.InstallLog", "\"JMH.SharePoint.CustomInstaller, Version=, Culture=neutral, PublicKeyToken=0122d41e560c7f87\"");


  40:                 ProcessStartInfo processStartInfo = new ProcessStartInfo(@"C:\Windows\Microsoft.NET\Framework64\v2.0.50727\installutil.exe", installerArguments);


  42:                 processStartInfo.RedirectStandardOutput = true;

  43:                 processStartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;

  44:                 processStartInfo.UseShellExecute = false;


  46:                 Process installerProcess = Process.Start(processStartInfo);

  47:                 StreamReader processResults = installerProcess.StandardOutput;


  49:                 //  Wait in milliseconds (ms) 1k ms = 1 sec

  50:                 installerProcess.WaitForExit(3000);


  52:                 if (installerProcess.HasExited)

  53:                 {

  54:                     EventLog.WriteEntry("JMH", processResults.ReadToEnd());

  55:                 }

  56:             }

  57:             catch (Exception)

  58:             {

  59:                 //  Log error here

  60:             }

  61:         }

  62:     }

  63: }

Notice I’m writing a message to the event log using the source I’ll be creating. This should let us know whether our installer worked or not. See line: EventLog.WriteEntry(“JMH”, processResults.ReadToEnd());

Few things to note:

1. My installer and the feature are all in the same project. My project is not an executable. I am using an Assembly DLL here. So in order for me to load the custom installer file, I have to reference the assembly by its fully qualifying name.

2. I added few lines of code to do some clean up. You may have some trouble installing or loading your custom installer file. If so, ensure that you reset IIS and retract and redeploy the package.

Finally, here’s what we got. We have a new Event Log source and Log file created. We logged our actions in a installer log file. We’re using a SharePoint 2010 feature to do this. Here are some final screen shots.

The after-look of our Visual Studio 2010 solution –


The installer log file –


The JMH custom event log –


References – Here are the references I used to write this blog entry.

MSDN (Event Log Installer) –

MSDN (InstallUtil.exe) –

MSDN (Delete Event Source) –

stackoverflow (Returning results from a process) –

Hope this was helpful.

Have a great New Year.

Posted in SharePoint Development

Upload a File into a SharePoint Library using Copy Web Service

You probably seen something similar to what I’m about to show you all over the internet. I will be using the Copy Web Service. This service is used to add or copy files from disparate SharePoint sites to other sites or can be used to simply upload files to your SharePoint libraries.

Information about this service can be found here

Here is a simple code snippet that will upload a file you’ve selected from the Open File Dialog we all use everyday. I’ve written this inside of a WPF application. You will need to reference the Copy Service and erase or comment some lines in order for you to use it in your application.

   1: private void btnBrowse_Click(object sender, RoutedEventArgs e)

   2:         {

   3:             try

   4:             {

   5:                 _copyProxy = new SharePoint3CopyService.Copy();

   6:                 _copyProxy.Credentials = credentials;

   7:                 _copyProxy.Url = copyWebServiceRelativeUrl;

   8:                 _copyProxy.CopyIntoItemsCompleted += new SharePoint3CopyService.CopyIntoItemsCompletedEventHandler(copyProxy_CopyIntoItemsCompleted);           


  10:                 OpenFileDialog openFileDialog = new OpenFileDialog();

  11:                 openFileDialog.RestoreDirectory = true;


  13:                 DialogResult dialogResult = openFileDialog.ShowDialog();


  15:                 FileInfo fileInfo = new FileInfo(openFileDialog.FileName);


  17:                 byte[] fileBytes;


  19:                 if (fileInfo.Exists)

  20:                 {

  21:                     Stream fileStream = null;


  23:                     string[] destinationUrls = { Uri.EscapeUriString(portalUrl + "/" + listName + "/" + openFileDialog.SafeFileName) };


  25:                     using (fileStream = openFileDialog.OpenFile())

  26:                     {

  27:                         fileBytes = new byte[fileStream.Length];


  29:                         int numBytesToRead = (int)fileStream.Length;

  30:                         int numBytesRead = 0;

  31:                         while (numBytesToRead > 0)

  32:                         {

  33:                             // Read may return anything from 0 to numBytesToRead.

  34:                             int n = fileStream.Read(fileBytes, numBytesRead, numBytesToRead);


  36:                             // Break when the end of the file is reached.

  37:                             if (n == 0)

  38:                                 break;


  40:                             numBytesRead += n;

  41:                             numBytesToRead -= n;

  42:                         }

  43:                     }


  45:                     SharePoint3CopyService.FieldInformation fieldInformation = new SharePoint3CopyService.FieldInformation();

  46:                     SharePoint3CopyService.FieldInformation[] information = { fieldInformation };


  49:                     _copyProxy.CopyIntoItemsAsync(openFileDialog.FileName, destinationUrls, information, fileBytes);

  50:                 }

  51:             }

  52:             catch (Exception ex)

  53:             {

  54:                 selfErrorMessageBuilder.Append(ex.Message);

  55:                 logger.Error("Method: btnBrowse_Click", ex);

  56:             }

  57:         }


The code above does the following

a. Gets a reference to the Copy Service (in Visual Studio Web References)

b. Passes a set of credentials. Here, I use Network Credentials –

c. I subscribe to the Completed Event

d. Open a new File Dialog so I can select the file to upload

e. Get a FileInfo reference to the File I’ll be working with

f. Set my destination URL. This includes my SharePoint site + Library + File name. I use the SafeFileName property to get the extension of the file along with its name

g. I go ahead and read the stream of bytes till I reach the end. I do this read using the FileStream.Read operation. This will allow me to Write the bytes I ‘m reading into a buffer. More info on this can be found here.

h. The FieldInformation class array is simply empty here. I don’t do much with it. I usually use this if I want to keep my metadata intact on the file

Till next time, take it easy!

Posted in SharePoint Development

One Option to Writing a Base Web User Control

Technorati Tags:

Today I was looking into writing a base web user control to act as an abstract class for other controls. The reason is I had several forms I needed to build and all share the same set of arguments. I looked at creating an interface, but it didn’t cut it for me.  See this reference for more on choosing abstract classes versus interfaces – 

Here’s an example of what I was trying to do.

1. Create my base user control. Notice the use of a Virtual method. This will allow me to override the method in my derived class without needing an abstract access modifier declaration on the class itself. Abstract modifiers are not supported on partial classes.

   1: <%@ Control Language="C#" AutoEventWireup="true" 
   2:     CodeBehind="BaseUserControl.ascx.cs" 
   3:     Inherits="Webeccentric.web.UserControls.BaseUserControl" %>
   1: namespace Webeccentric.web.UserControls
   2: {
   3:     public partial class BaseUserControl : System.Web.UI.UserControl
   4:     {
   5:         int _reviewMonth;
   6:         int _reviewYear;
   8:         public int ReviewMonth { get { return _reviewMonth; } set { _reviewMonth = value; } }
   9:         public int ReviewYear { get { return _reviewYear; } set { _reviewYear = value; } }
  11:         public virtual void Save(){}
  12:     }
  13: }

2. Create a user control that will inherit from my base user control

   1: <%@ Control Language="C#" AutoEventWireup="true" 
   2:     CodeBehind="Review.ascx.cs" 
   3:     Inherits="Webeccentric.web.UserControls.Review" %>
   4:     <div>
   5:         <asp:Label ID="lblMonth" runat="server" Text="" />
   6:     </div>
   7:     <div>
   8:         <asp:Label ID="lblYear" runat="server" Text="" />
   9:     </div>
  10:     <div>
  11:         <asp:Button id="btnSubmit" runat="server" Text="Click Me" 
  12:             onclick="btnSubmit_Click" />
  13:     </div>
   1: namespace Webeccentric.web.UserControls
   2: {
   3:     public partial class Review : BaseUserControl
   4:     {
   5:         protected override void OnLoad(EventArgs e)
   6:         {
   7:             lblMonth.Text = ReviewMonth.ToString();
   8:             lblYear.Text = ReviewYear.ToString();
   9:         }
  11:         public override void Save()
  12:         {
  13:             //  Implement the Save operation here
  14:             //  ...
  15:         }
  17:         protected void btnSubmit_Click(object sender, EventArgs e)
  18:         {
  19:             Save();
  20:         }
  21:     }
  22: }

3. Create a Page to test the concept and load the control in it

   1: <form id="form1" runat="server">
   2: <div>
   3:     <asp:Panel ID="pnlUserControl" runat="server"></asp:Panel>
   4: </div>
   5: </form>
   1: public partial class _Default : System.Web.UI.Page
   2:     {
   3:         protected void Page_Load(object sender, EventArgs e)
   4:         {
   6:         }
   8:         protected override void CreateChildControls()
   9:         {
  10:             base.CreateChildControls();
  12:             //  Load custom user control with some initial values
  13:             Review review = (Review)Page.LoadControl(@"/UserControls/Review.ascx");
  14:             review.ReviewMonth = 10;
  15:             review.ReviewYear = 2010;
  17:             pnlUserControl.Controls.Add(review);
  18:         }
  19:     }

4. That’s it. This should work now.

Hope this helps.

Posted in General ASP.NET Development | Leave a comment

Before SharePoint Client Object Model – Using Web Services to Consume SharePoint 3.0 Data in WPF

Technorati Tags: ,

I am thinking about posting a few entries on how we would go about consuming SharePoint data. There are many options out there. I’ll start with the good old web services way. Using SharePoint ASMX web services will allow you to consume List and Site Data as well as do many administrative tasks, such as creating sites and pages to web part and list management.

Reference to v3.0 and MOSS 2007 web services –

Scenario – View all lists and libraries on a SharePoint site using the Lists web service [http://wsssite/_vti_bin/Lists.asmx]

I’ve got a WPF desktop application with a single Page. This page will need to have a TAB control. One of its Tabs will need to list all available SharePoint Lists and Libraries on a given site.

Solution – Overall approach and steps

Step One – Firstly, assuming you’ve got all that you need. A WSS 3.0 or a MOSS 2007 site with some lists and libraries. By default you should have some. You also got Visual Studio and a WPF Desktop application built. You go ahead and add a web service reference to the Lists ASMX service mentioned above. Go a step further and define a class that will eventually hold your List data.

Here’s a code snippet to a WPF Tab Control with one Tab in it.


Step Two – Secondly, we start in the code behind. We’ll need few things. I went ahead and defined a class to hold my List Data. Here it is.


Step Three – Thirdly make sure you’ve got your web service referenced and such. Let’s add some code to call on it during the WPF page initialization and loading.


In addition to service reference, you will need references to LINQ and Threading.


Step Four – Wire it up and load the list of all libraries available on the site


Notice the use of Threading and Asynchronous calls into the web service. Why, well, simply put so the WPF UI doesn’t get stuck on the call to the web service and you could load the Tab control without affecting the user experience.

Step Five – Code the actual work to be done

   1: void worker_DoListsLibrariesWork(object sender, DoWorkEventArgs e)
   2:         {
   3:             try
   4:             {
   5:                 _listProxy = new SharePoint3ListsService.Lists();
   6:                 _listProxy.Url = listsWebServiceRelativeUrl;
   7:                 _listProxy.Credentials = credentials;
   9:                 _listProxy.GetListCollectionCompleted += new SharePoint3ListsService.GetListCollectionCompletedEventHandler(_listProxy_GetListCollectionCompleted);
  10:                 _listProxy.GetListCollectionAsync();
  11:             }
  12:             catch (Exception ex)
  13:             {
  14:                 //
  15:             }
  16:         }
  18:         void _listProxy_GetListCollectionCompleted(object sender, SharePoint3ListsService.GetListCollectionCompletedEventArgs e)
  19:         {
  20:             try
  21:             {
  22:                 XElement results = XElement.Parse(e.Result.OuterXml, LoadOptions.None);
  24:                 var linqQuery = from x in results.Descendants() select x;
  26:                 List<SPList> items = new List<SPList>();
  28:                 foreach (XElement x in linqQuery)
  29:                 {
  30:                     if (x.Attribute("Title").Value != null)
  31:                     {
  32:                         items.Add(new SPList
  33:                             {
  34:                                 Title = (x.Attribute("Title").Value != null) ? x.Attribute("Title").Value : null,
  35:                                 DefaultViewUrl = (x.Attribute("DefaultViewUrl").Value != null) ? x.Attribute("DefaultViewUrl").Value : null,                                
  36:                             });
  37:                     }                   
  38:                 }
  40:                 var action = new Action<List<SPList>>(UpdateListsLibrariesBox);
  42:                 Dispatcher.BeginInvoke(DispatcherPriority.Input, action, items);
  43:             }
  44:             catch (Exception ex)
  45:             {
  46:                 //
  47:             }
  48:         }
  50:         void UpdateListsLibrariesBox(List<SPList> lists)
  51:         {
  52:             listBoxLibraries.ItemsSource = lists;
  53:         }
  55:         void worker_ListsLibrariesProgressChanged(object sender, ProgressChangedEventArgs e)
  56:         {
  58:         }
  60:         void worker_RunListsLibrariesWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
  61:         {
  63:         }

Summary – This is just one option of how to consume SharePoint data in your client application. Next time I’ll try to demonstrate how to do that using SharePoint 2010 Client Object Model.

Take it easy.

Posted in SharePoint Development | Leave a comment

Convert Office Word Documents Stored In SharePoint to PDF Using Save As PDF Add In

A while back I was working on a project where we had to convert a massive amount of documents into PDF with minimal intervention. We looked at several products and compared their features as well as their pricing and value-add. Our budget was limited and this functionality was not really needed at all times. The solution didn’t require any robust mechanism for automating this and our client was open for creative solutions.

This post is meant to describe the solution we ended up with along with some code snippets and reference material.

Given the above situation, the solution from a very high level utilized the Save As Add In available for free and the SharePoint Copy Web service to convert the Word documents into PDF. The solution was built in Visual Studio 2005 as a Windows Forms Application that ran on a desktop Win XP SP2 machine.

Steps to Convert

  1. Retrieved the Office document stored in a SharePoint Library
  2. Save the document retrieved in the Windows Temp folder
  3. Convert the document to PDF
  4. Upload the document now converted to PDF back into the SharePoint Library
  5. All of that keeping document metadata intact

Code Snippet

1. Add references to the Copy web service and Word Interop Assembly

   1: using CopyService;
   2: using Microsoft.Office.Interop.Word;

2. This piece of code here takes input from a multiline textbox that contains all Word documents to be converted. Of course, you may call SharePoint Lists web service and get your File names that way too.


    //  Copy Web service
    CopyService.Copy service = new CopyService.Copy();               
    service.Credentials = System.Net.CredentialCache.DefaultCredentials;

    string tempPath = Path.GetTempPath();
    string tempFolder = “ConvertDocToPDF”;
    string tempPathComplete = tempPath + tempFolder;

    //  Create a temp folder to save all converted files
    if (!Directory.Exists(tempPathComplete))

    foreach (string lineFileName in txtFileName.Lines)
        if (lineFileName.IndexOf(“.pdf”) <= 0)
            string fileNameComplete = lineFileName; //  Includes the extension
            string filePathComplete = tempPathComplete + “/” + fileNameComplete;

            string fileName = lineFileName.Remove(lineFileName.LastIndexOf(“.”)); //    Remove the extension
            string localDestinationFilePath = tempPathComplete + “/” + fileName + “.pdf”;

            string copySourceFilePath = txtSharePointSiteUrl.Text + “/” + txtSharePointLibraryName.Text + “/” + lineFileName;
            byte[] sourceFileArray = null;

            string[] destinationUrls = new string[] { txtSharePointSiteUrl.Text + “/” + txtSharePointLibraryName.Text + “/” + fileName + “.pdf” };

            CopyService.FieldInformation fieldInformation = new CopyService.FieldInformation();
            CopyService.FieldInformation[] fieldInformationArray = { fieldInformation };

            CopyService.CopyResult copyResult1 = new CopyService.CopyResult();
            CopyService.CopyResult copyResult2 = new CopyService.CopyResult();
            CopyService.CopyResult[] copyResultArray = { copyResult1, copyResult2 };

            uint fileUint = service.GetItem(copySourceFilePath, out fieldInformationArray, out sourceFileArray);

            //  Check to see if the original file exists, and if so, remove it
            if (File.Exists(filePathComplete))

            if (File.Exists(filePathComplete.Remove(filePathComplete.LastIndexOf(“.”)) + “.pdf”))
                File.Delete(filePathComplete.Remove(filePathComplete.LastIndexOf(“.”)) + “.pdf”);

            //  Write the bytes array from GetItem to local user temporary folder             
            File.WriteAllBytes(filePathComplete, sourceFileArray);

            //  Start working on converting the downloaded file to PDF
            ApplicationClass wordApplication = new ApplicationClass();
            Document wordDocument = null;

            object paramSourceDocPath = filePathComplete;
            object paramMissing = Type.Missing;

            string paramExportFilePath = localDestinationFilePath;
            WdExportFormat paramExportFormat = WdExportFormat.wdExportFormatPDF;
            bool paramOpenAfterExport = false;

            WdExportOptimizeFor paramExportOptimizeFor = WdExportOptimizeFor.wdExportOptimizeForPrint;
            WdExportRange paramExportRange = WdExportRange.wdExportAllDocument;

            int paramStartPage = 0;
            int paramEndPage = 0;

            WdExportItem paramExportItem = WdExportItem.wdExportDocumentContent;
            bool paramIncludeDocProps = true;
            bool paramKeepIRM = true;

            WdExportCreateBookmarks paramCreateBookmarks = WdExportCreateBookmarks.wdExportCreateWordBookmarks;
            bool paramDocStructureTags = true;
            bool paramBitmapMissingFonts = true;
            bool paramUseISO19005_1 = false;

            // Try to convert the downloaded file
                // Open the source document.
                wordDocument = wordApplication.Documents.Open(
                    ref paramSourceDocPath, ref paramMissing, ref paramMissing,
                    ref paramMissing, ref paramMissing, ref paramMissing,
                    ref paramMissing, ref paramMissing, ref paramMissing,
                    ref paramMissing, ref paramMissing, ref paramMissing,
                    ref paramMissing, ref paramMissing, ref paramMissing,
                    ref paramMissing);

                // Export it in the specified format.
                if (wordDocument != null)
                        paramExportFormat, paramOpenAfterExport,
                        paramExportOptimizeFor, paramExportRange, paramStartPage,
                        paramEndPage, paramExportItem, paramIncludeDocProps,
                        paramKeepIRM, paramCreateBookmarks, paramDocStructureTags,
                        paramBitmapMissingFonts, paramUseISO19005_1,
                        ref paramMissing);
            catch (Exception ex)
                throw ex;
                // Close and release the Document object.
                if (wordDocument != null)
                    wordDocument.Close(ref paramMissing, ref paramMissing, ref paramMissing);
                    wordDocument = null;

                // Quit Word and release the ApplicationClass object.
                if (wordApplication != null)
                    wordApplication.Quit(ref paramMissing, ref paramMissing, ref paramMissing);
                    wordApplication = null;

                uint copyUint = service.CopyIntoItems(localDestinationFilePath, destinationUrls, fieldInformationArray, File.ReadAllBytes(localDestinationFilePath), out copyResultArray);                           
            catch (Exception exc)
catch (Exception ex)
    throw ex;
} </code>


Saving Word 2007 documents to PDF and XPS Formats on MSDN –

SharePoint Office Server Copy Web Service on MSDN –

Posted in SharePoint Development | Leave a comment