You need to create customized reports based on Sharepoint data and you don't have the access to the server to create a new web part to access it directly. You need to resort to other options to generate the report. Fortunately, Sharepoint allows some methods to access its data, so you can get the information you need. If you are using C#, you can use one of these three methods:
- Client Side Object Model (CSOM) - this is a set of APIs that allow access to the Sharepoint data and allow you to maintain lists and documents in Sharepoint
- REST API - with this API you can access Sharepoint data, not only using C#, but with any other platform that can perform and process REST requests, like web or mobile apps
- SOAP Web Services - although this kind of access is being deprecated, there are a lot of programs that depend on it, so it's being actively used until now. You can use this API with any platform that can process SOAP web services.
This article will show how to use these three APIs to access lists and documents from a Sharepoint server and put them in a WPF program, with an extra touch: the user will be able to export the data to Excel, for further manipulation.
To start, let's create a WPF project in Visual Studio and name it SharepointAccess. We will use the MVVM pattern to develop it, so right click the References node in the Solution Explorer and select Manage NuGet Packages and add the MVVM Light package. That will add a ViewModel folder, with two files in it to your project. The next step is to make a correction in the ViewModelLocator.cs file. If you open it, you will see an error in the line
Just replace this using clause with
The next step is to link the DataContext of MainWindow to the MainViewModel, like it's described in the header of ViewModelLocator:
Then, let's add the UI to MainWindow.xaml:
The first line in the grid will have a text box to enter the address of the Sharepoint site, a button to go to the address and three radiobuttons to select the kind of access you want.
The main part of the window will have three listboxes to show the lists on the selected site, the documents in each list and the properties of the document.
As you can see, we've used data binding to fill the properties of the UI controls. We're using the MVVM pattern and all these properties should be bound to properties in the ViewModel. The buttons and radiobuttons have their Command properties bound to a property in the ViewModel, so we don`t have to add code to the code behind file. We've also used templates for the items in the listboxes, so the data is properly presented.
The last line will show the timings for getting the data.
If you run the program, it will run without errors and you will get an UI like this, that doesn't do anything:
It's time to add the properties in the MainViewModel to achieve the functionality we want. Before that, we'll add two classes to manipulate the data that comes from the Sharepoint server, no matter the access we are using. Create a new folder named Model, and add these two files, Document.cs and DocumentsList.cs:
These are very simple classes, that will store the data that comes from the Sharepoint server. The next step is to get the data from the server. For that we will use a repository that gets the data and returns it using these two classes. Create a new folder, named Repository and add a new interface, named IListRepository:
This interface declares two methods, GetListsAsync and GetDocumentsFromListAsync. These are asynchronous methods because we don want them to block the UI while they are being called. Now, its time to create the first access to Sharepoint, using the CSOM API. For that, you must add the NuGet package Microsoft.SharePointOnline.CSOM . This package will provide all the APIs to access Sharepoint data. We can now create our first repository. In the Repository folder, add a new class and name it CsomListRepository.cs:
For accessing the Sharepoint data, we have to create a ClientContext, passing the Sharepoint site to access. Then, we get a reference to the Web property of the context and then we do a query for the lists that aren't hidden and that have any items in them. The query should return with the titles and description of the lists in the website. To get the documents from a list we use a similar way: create a context, then a query and load the items of a list.
We can call this code in the creation of the ViewModel:
This code will get the initial web site url from the configuration file for the app and call GoToAddress:
The method calls the GetListsAsync method of the repository to get the lists and sets the DocumentsLists property with the result.
We must also declare some properties that will be used to bind to the control properties in the UI:
These properties will trigger the PropertyChanged event handler when they are modified, so the UI can be notified of their change.
If you run this code, you will have something like this:
Then, we must get the documents when we select a list. This is done when the SelectedList property changes:
GetDocumentsForList is:
You have to declare the Documents and the Fieldsproperties:
One other change that must be made is to create a property named SelectedDocument that will be bound to the second list. When the user selects a document, it will fill the third list with the document's properties:
Now, when you click on a list, you get all documents in it. Clicking on a document, opens its properties:
Everything works with the CSOM access, so it's time to add the other two ways to access the data: REST and SOAP. We will implement these by creating two new repositories that will be selected at runtime.
To get items using the REST API, we must do HTTP calls to http://<website>/_api/Lists
and http://<website>/_api/Lists/GetByTitle('title')/Items
. In the Repository folder, create a new class and name it RestListRepository. This class should implement the IListRepository interface:
GetListsAsync will be:
GetResponseDocumentAsync will issue a HTTP Get request, will process the response and will return an XDocument:
The response will be a XML String. We could get the response as a Json object if we pass the accept header as application/json. After the document is parsed, we process all entry elements, retrieving the lists, in GetDocumentsListFromElement:
Here we filter the list by parsing the Hidden and ItemCount properties and returning an empty document if the document is hidden or has no items. GetDocumentsFromListAsync is:
It parses the XML and extracts a document and its properties. GetUrlFromTitle gets the Url from the Title property and is:
The third access method is using the Soap service that Sharepoint makes available. This access method is listed as deprecated, but it's still alive. You have to create a reference to the http://<website>/_vti_bin/Lists.asmx
and create a WCF client for it. I preferred to create a .NET 2.0 Client instead of a WCF service, as I found easier to authenticate with this service.
In Visual Studio, right-click the References node and select the Add Service Reference. Then, click on the Advanced button and then, Add Web Reference. Put the url in the box and click the arrow button:
When you click the Add Reference button, the reference will be added to the project and it can be used. Create a new class in the Repository folder and name it SoapListRepository. Make the class implement the IListRepository interface. The GetListsAsyncmethod will be:
As we are using the .NET 2.0 web service, in order to convert the call to an asynchronous method, we must use a TaskCompletionSource to detect when the call to the service returns. Then we fire the call to the service. When it returns, the completed event is called and sets the TaskCompletionSource to the desired state: canceled, if the call was canceled, exception, if there was an error or set the result if the call succeeds. Then, we remove the event handler for the completed event and process the result (a XmlNode), to transform into a list of DocumentsList.
The call to GetDocumentsFromListAsync is very similar to GetListsAsync:
The main difference is the processing of the response, to get the documents list. Once you have the two methods in place, the only thing to do is select the correct repository in MainViewModel. For that, we create an enum for the API Selection:
Then, we need to declare a command bound to the radiobuttons, that will receive a string with the enum value:
The last step is to select the repository in the GoToAddress method:
With the code in place, you can run the app and see the data shown for each API.
One last change to the program is to add a command bound to the Go button, so you can change the address of the web site and get the lists and documents for the new site:
This command has an extra touch: it will only enable the button if there is an address in the address box. If it's empty, the button will be disabled. Now you can run the program, change the address of the website, and get the lists for the new website.
Conclusions
As you can see, we've created a WPF program that uses the MVVM pattern and accesses Sharepoint data using three different methods - it even has a time measuring feature, so you can check the performance difference and choose the right one for your case.
The full source code for this project is at https://github.com/bsonnino/SharepointAccess