Blog Map
[Blog Map] This blog is inactive. New blog: EricWhite.com/blog
Web services are one of the most effective and convenient ways for casual developers to access SharePoint lists and document libraries. They have a reputation for being a bit difficult; LINQ to XML can make them easier to use. This post presents the basic steps for getting started with Windows SharePoint Services Web Services using LINQ to XML (either C# or VB).
In several upcoming posts, I’ll present some more information about using web services, as well as more notes on the code presented in this post. There are some interesting and easy ways to explore SharePoint web services using LINQ to XML. However, before addressing more involved scenarios, I want to make sure that you can get started easily.
First, a few points about SharePoint web services. They can be disabled for a SharePoint site, but by default, they are enabled. In most cases, it is easy to use them; if you have permissions to manually create and modify documents for a site, you probably can use web services to do so too.
One important feature of SharePoint that enables effective collaboration is the My Site feature. For an introduction to your My Site, see this Office Online article. Chances are, if you have a My Site in your company, you can use web services to programmatically access it. In an upcoming project, I plan to use the SharePoint collaboration features to make managing the project easier. Then I'll write a little C# program that collects information from lists and document libraries (using web services) and produces a nicely formatted status report as an Open XML Wordprocessing document, and then places the report into an appropriate document library.
Create a new Windows Console application (either C# or VB).
Important note: Pay attention to the name that you give your application, as the classes created to access the SharePoint web services will be in the namespace of your application. For this example, name the application SPWebServicesExample.
Add a reference to your SharePoint web service. Select Project, Add Service Reference…
Click the Advanced button:
Click the ‘Add Web Reference’ button:
Click the Go button to confirm the URL. If you have entered a valid URL, then this dialog box tells you that it found a web service. The dialog box will be populated with the various operations available in the web service.
Change the web reference name to something relevant. For accessing the Lists web service, a good web reference name is ‘ListsWebService’.
Click the Add Reference button to add this reference to your project.
Following is a small example to get all of the lists and list items in a site. The example creates a small XML "report" that contains relevant data on the lists and items. In addition to the listing on this page, I've attached the code to this post.
In general, when using this code as boilerplate, you have to remember to update three things (all highlighted in the listing below):
Note that if you used the names suggested earlier, you will not need to update the first two items, as the web service proxy will already be set to “SPWebServicesExample” and the web reference name will already be set to “ListsWebService”.
There are a couple of notes to make about the following code:
It is more convenient to use LINQ to XML instead of XmlDocument for accessing web services. You can write simpler, easier to read code when creating the XML that you pass as arguments to operations. In particular, for this purpose, VB XML literals rock! And the code to query the XML returned by the web service is much easier to write, in my opinion.
I'll be blogging more about how to use these web services. There's a lot that you can do with them. I am especially enthused about taking advantage of what you can do with Open XML and the Open XML SDK. Stay tuned...
Imports System.Xml
Imports System.Text
Module Module1
<System.Runtime.CompilerServices.Extension()> _
Public Function GetXElement (ByRef node As XmlNode) As XElement
dim xDoc as XDocument = new XDocument()
using xmlWriter as XmlWriter = xDoc.CreateWriter()
node.WriteTo(xmlWriter)
End Using
return xDoc.Root
End Function
Public Function GetXmlNode (ByRef element As XElement) As XmlNode
Using xmlReader as XmlReader = element.CreateReader()
Dim xmlDoc As XmlDocument = New XmlDocument
xmlDoc.Load(xmlReader)
Return xmlDoc
Public Function ToStringAlignAttributes(ByVal element As XElement) As String
Dim settings As XmlWriterSettings = New XmlWriterSettings()
settings.Indent = True
settings.OmitXmlDeclaration = True
settings.NewLineOnAttributes = True
Dim stringBuilder As StringBuilder = New StringBuilder()
Using xmlWriter As XmlWriter = xmlWriter.Create(stringBuilder, settings)
element.WriteTo(xmlWriter)
Return stringBuilder.ToString()
Sub Main()
Dim s as XNamespace = "http://schemas.microsoft.com/sharepoint/soap/"
Dim rs as XNamespace = "urn:schemas-microsoft- com:rowset"
Dim z as XNamespace = "#RowsetSchema"
' Make sure that you use the correct namespace, as well as the correct reference name.
' The namespace (by default) is the same as the name of the application when you
' created it. You specify the reference name in the Add Web Reference dialog box.
'
' Namespace Reference Name
' | |
' V V
Dim lists As SPWebServicesExample.ListsWebService.Lists = _
New SPWebServicesExample.ListsWebService.Lists()
' Update the following URL to point to the Lists web service
' for your SharePoint site.
lists.Url = http://my/sites/your-alias-here/_vti_bin/Lists.asmx
'lists.Url = "http://xyzteamsite/_vti_bin/Lists.asmx";
lists.Credentials = System.Net.CredentialCache.DefaultCredentials
Dim queryOptions = _
<QueryOptions>
<Folder/>
<IncludeMandatoryColumns>false</IncludeMandatoryColumns>
</QueryOptions>
Dim viewFields = <ViewFields/>
dim listCollection as XElement = lists.GetListCollection().GetXElement()
Dim report as XElement = _
<Report>
<%= listCollection _
.Elements(s + "List") _
.Select( Function(l) _
new XElement("List", _
l.Attribute("Title"), _
l.Attribute("DefaultViewUrl"), _
l.Attribute("Description"), _
l.Attribute("DocTemplateUrl"), _
l.Attribute("BaseType"), _
l.Attribute("ItemCount"), _
l.Attribute("ID"), _
lists.GetListItems(l.Attribute("ID"), "", Nothing, _
viewFields.GetXmlNode(), "", queryOptions.GetXmlNode(), "") _
.GetXElement() _
.Descendants(z + "row") _
.Select (Function(r) _
new XElement ("Row", _
r.Attribute("ows_Title"), _
r.Attribute("ows_ContentType"), _
r.Attribute("ows_FSObjType"), _
r.Attribute("ows_Attachments"), _
r.Attribute("ows_FirstName"), _
r.Attribute("ows_LinkFilename"), _
r.Attribute("ows_EncodedAbsUrl"), _
r.Attribute("ows_BaseName"), _
r.Attribute("ows_FileLeafRef"), _
r.Attribute("ows_FileRef"), _
r.Attribute("ows_ID"), _
r.Attribute("ows_UniqueId"), _
r.Attribute("ows_GUID") _
) _
) %>
</Report>
Console.WriteLine (report.ToStringAlignAttributes())
End Sub
End Module
After you build and run this example, your output should look like this. Note that for even a small SharePoint site, this may run several thousand lines long, so you may have to redirect the output to a file or change the screen buffer height on the command prompt window to view it all.
<List
Title="AList"
DefaultViewUrl="/sites/ericwhit/AList/Forms/AllItems.aspx"
Description="AList"
DocTemplateUrl="/sites/ericwhit/AList/Forms/template.dotx"
BaseType="1"
ItemCount="0"
ID="{AA12AA75-2422 -48BB-B41A-267C61D7A54F}" />
Title="Eric White's Wiki"
DefaultViewUrl="/sites/ericwhit/Eric Whites Wiki/Forms/AllPages.aspx"
Description="Wiki"
DocTemplateUrl=""
ItemCount="3"
ID="{AA0A2753-5A94 -42C1-BAA7-66DD1409CD3E}">
<Row
ows_ContentType="Wiki Page"
ows_FSObjType="2;#0"
ows_LinkFilename="Home.aspx"
ows_EncodedAbsUrl="http://my/sites/ericwhit/Eric%20Whites%20Wiki/Home.aspx"
ows_BaseName="Home"
ows_FileLeafRef="2;#Home.aspx"
ows_FileRef="2;#sites/ericwhit/Eric Whites Wiki/Home.aspx"
ows_ID="2"
ows_UniqueId="2;#{AA6833E4-98F2-42C4-9355-6DF2453DC7D1}"
ows_GUID="{AAEA7CFF-9FE1-47F9-8C48-94B631289D0F}" />
...
PingBack from http://www.codedstyle.com/getting-started-with-sharepoint-wss-web-services-using-linq-to-xml/
Here is a list on links that I want to share with you. LINQ for Office Developers Some Office solutions
XNamespace s = "http://schemas.microsoft.com/sharepoint/soap/";
XNamespace rs = "urn:schemas-microsoft-com:rowset";
XNamespace z = "#RowsetSchema";
=> How to know these namespaces exactly, Eric?
Could you show me how many kind of namespaces there are?
Thanks.
Hi Chubby,
Namespaces are a part of XML. Within XML, elements and attributes can be in namespaces, or in no namespace. When a software engineer or software designer puts together a particular XML document, he or she can decide to put elements and/or attributes in any namespace that they choose. In the code presented in this document, we deal with namespaces associated with SOAP. When dealing with Open XML, we use namespaces defined by the Open XML standard. It's probably worthwhile to read a book on XML, and understand how to deal with namespaces. One book that does a great job of explaining namespaces is Patricia Walmsleys book, 'Definitive XML Schema'. It discusses namespaces in the context of XSD, which is a somewhat advanced topic. I'm sure there are other books that more directly explain namespaces, but unfortunately, I don't have any recommendations.
If anyone else has a good recommendation for a beginning XML book that does a good job of explaining namespaces, feel free to leave a comment here...
-Eric
VB samples "Function(l)" and "Function(r)" not working
Hi Eric,
novice... managed to complete everything in your example... build goes ok with no errors... however when start debugging the console window comes up but nothing ever comes back... is there something basic that needs to be added to the project that I missed?
I've been trying to find out how to add a 'web reference' via the 'service reference' option in VS2008 and this really helped.
Many thanks!
Thanks so much for the complete example, works perfectly for me!
@Glynn: How long did you wait to see if anything came up? It takes my machine 30s - 1min to actually start writing the XML to the console.
Hi Eric, great post. I'm now thinking about reusing this code for other SP web services, for example the "AddList" method of the Lists web service. I have an idea as to how to start, for example by taking the large Linq to XML statement and putting it in a method called CallGetListsCollection and return the XElement. I suppose I'll just start hacking away and see what I come up with, but wonder if you had any thoughts on whether there's a clean way to reuse such code for different methods like "AddList", "CreateContentType" etc.
Hi David,
The approach that I would take is to parameterize the large LINQ to XML functional construction statement. However, this statement will, for the most part, be unique to the particular web service. I would have different methods for each web service, each with their own code to create the XML.
Thanks for that advice, much appreciated. It will be a good exercise for me.
Nice article. For an object which does the Linq to XML (using VB.Net which supports XML Literals -- you should check it out) see this link:
sqlsrvintegrationsrv.codeplex.com/.../53230
Thanks, I'd love an example of using Query service to return search results.
Hi, When I enter the code I get an error for the lists URL reference in the code. The URL does resolve in a browser or click on the link in the code. The error I am getting is "Error 2 Cannot implicitly convert type 'string' to 'SPWebServicesExample.ListsWebService.Lists'
I am using the namespace conventions as per you article. Please help