Entries RSS

How to read SharePoint data from Adobe Flex

Flex, SharePoint Add comments

This article describes how to access and read SharePoint data from MOSS 2007 and WSS 3.0 into Adobe Flex applications using the built-in SharePoint web services along with a custom web service that acts as a proxy between your Flex application and SharePoint.

Here is the ASP.NET Web Service code:

Imports System.Web
Imports System.Web.Services
Imports System.Web.Services.Protocols
Imports System.Xml
 
<WebService(Namespace:="http://tempuri.org/SharePointService")> _
<WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Public Class SharePointService
    Inherits System.Web.Services.WebService
 
    <WebMethod(MessageName:="GetSharePointListXML", Description:="<p></p>")> _
    Public Function GetSharePointListXML(ByVal sSiteUrl As String, ByVal sListGUID As String, ByVal sViewGUID As String, ByVal sFieldsList As String, ByVal sQuery As String) As System.Xml.XmlNode
        Dim listService As New SPListsWS.Lists()
        Dim nodeListItems As System.Xml.XmlNode
        Dim xmlDoc As New System.Xml.XmlDocument()
        Dim listGuid As String = sListGUID
        Dim viewGuid As String = sViewGUID
        Dim query As System.Xml.XmlElement = xmlDoc.CreateElement("Query")
        Dim viewFields As System.Xml.XmlElement = xmlDoc.CreateElement("ViewFields")
        Dim queryOptions As System.Xml.XmlElement = xmlDoc.CreateElement("QueryOptions")
        Dim rowLimit As String = "10000"
        Dim arTemp As Array
        Dim sTemp As String = ""
        Dim x As Integer
 
        listService.PreAuthenticate = True
        listService.Credentials = System.Net.CredentialCache.DefaultCredentials
        listService.Url = sSiteUrl.Trim("/", " ") & "/_vti_bin/Lists.asmx"
 
        query.InnerXml = sQuery
        If Not sFieldsList Is Nothing And Not sFieldsList = "" Then
            arTemp = Split(sFieldsList, ",")
            If arTemp.Length > 0 Then
                For x = 0 To arTemp.Length - 1
                    sTemp += "<FieldRef Name=""" & CType(arTemp(x), String).Trim() & """ />"
                Next
            End If
        End If
        viewFields.InnerXml = sTemp
        queryOptions.InnerXml = "<IncludeMandatoryColumns>FALSE</IncludeMandatoryColumns><DateInUtc>FALSE</DateInUtc>"
 
        nodeListItems = listService.GetListItems(listGuid, viewGuid, query, viewFields, rowLimit, queryOptions, Nothing)
 
        Return CleanUpSharePointXML(nodeListItems)
    End Function
 
    Public Function CleanUpSharePointXML(ByVal xmlNode As System.Xml.XmlNode) As System.Xml.XmlNode
        Dim xmlString As String = xmlNode.OuterXml()
        Dim xmlDoc As New System.Xml.XmlDocument
        Dim pattern1 As Regex = New Regex("rs:data")
        Dim pattern2 As Regex = New Regex("z:row")
        Dim pattern3 As Regex = New Regex("<listitems.*>")
        Dim pattern4 As Regex = New Regex(" ows_")
        'Dim pattern5 As Regex = New Regex("<Results.*>")
 
        xmlString = pattern1.Replace(xmlString, "data")
        xmlString = pattern2.Replace(xmlString, "row")
        xmlString = pattern3.Replace(xmlString, "<listitems>")
        xmlString = pattern4.Replace(xmlString, " ")
        'xmlString = pattern5.Replace(xmlString, "<Results>")
        xmlDoc.LoadXml(xmlString)
 
        Return xmlDoc
    End Function
 
End Class

When you create your web service, make sure you add a web reference within your Visual Studio project to the Lists.asmx web service - The url should be http://myserver/_vti_bin/Lists.asmx. Make sure to replace myserver with your SharePoint server name. Here is a quick screencast of how to add the web reference. Also, this proxy web service must be on the same server as SharePoint.

Now that you have a web service that gets and updates data within any SharePoint list or document library, let’s see below how you would use it in your Flex application. We are going to assume you deployed your web service and it is accessible through http://myserver/services/SharePointService.asmx or where ever else you have deployed it and named it.

<mx:WebService id="sharepointService" useProxy="false"
    wsdl="http://myserver/services/SharePointService.asmx?WSDL"
    showBusyCursor="true" fault="wsFaultHandler(event)">
    <mx:operation name="GetSharePointListXML" resultFormat="e4x" 
        result="getSharePointListXMLResult(event)">
	<mx:request>
	    <sSiteUrl>{siteUrl}</sSiteUrl>
	    <sListGUID>{listGUID}</sListGUID>
	    <sViewGUID>{viewGUID}</sViewGUID>
	    <sFieldsList>{fieldsList}</sFieldsList>
	    <sQuery>{query}</sQuery>
	</mx:request>
    </mx:operation>
</mx:WebService>
 
<mx:Script>
    <![CDATA[
        import mx.collections.*;
        import mx.utils.ArrayUtil;
    	import mx.rpc.events.ResultEvent;
    	import mx.rpc.events.FaultEvent;
 
	private namespace ns1 = "http://tempuri.org/SharePointService"; 
	private namespace ns2 = "http://tempuri.org/XMLSchema.xsd";
        use namespace ns1;
        use namespace ns2;
 
	[Bindable] private var siteUrl:String;
	[Bindable] private var listGUID:String;
	[Bindable] private var viewGUID:String;
	[Bindable] private var fieldsList:String;
	[Bindable] private var query:String;
	[Bindable] private var dataXMLList:XMLListCollection;
 
 
	public function wsFaultHandler(event:FaultEvent):void 
	{
		Alert.show(event.fault.message, "Fault");
	}
 
	private function doInitialize():void 
	{
		siteUrl = "http://myserver/sites/mysite/";
		listGUID = "D388638E-D34E-437F-9A1C-45BFBC85F266";
		viewGUID = "";
		fieldsList = "Title,Description,Type,Profit";
		query = "";
 
		sharepointService.GetSharePointListXML.send();
	}
 
        private function GetSharePointListXMLResult(event:ResultEvent):void 
        {
    		dataXMLList = new XMLListCollection(new XMLList(event.result.data.row));
        }
    ]]>
</mx:Script>
 
<mx:DataGrid width="80%" height="80%" dataProvider="{dataXMLList}">
    <mx:columns>
	<mx:DataGridColumn headerText="Title" dataField="Title" />
	<mx:DataGridColumn headerText="Description" dataField="Description" />
	<mx:DataGridColumn headerText="Type" dataField="Type" />
	<mx:DataGridColumn headerText="Profit" dataField="Profit" />
    </mx:columns>
</mx:DataGrid>

Update: Next, I demonstrate how to add, delete, and update SharePoint data from within your Adobe Flex application by expanding on our proxy web service above and preparing an updateQuery XML string to be processed by SharePoint.

31 Responses to “How to read SharePoint data from Adobe Flex”

  1. Serge van den Oever [Macaw] Says:

    Hi Markuso,

    Great article! Good to see some more info on using SharePoint from Flex. I have a rewrite of my weblog post http://weblogs.asp.net/soever/archive/2005/10/29/428902.aspx published at the Flex Cookbook: http://www.adobe.com/cfusion/communityengine/index.cfm?event=showdetails&productId=2&postId=7743

    Hope to see more blog posts from you on this topic!

    Good luck!

    Serge

  2. Marc Says:

    Hi Markuso, thanks for this article… very helpful! Looking forward to the updateQuery XML example.

  3. Ashish Says:

    Hi,
    when i tried this example, web service has no issue. but the flex code didn’t get data @ line
    “dataXMLList = new XMLListCollection(new XMLList(event.result.data.row));”.
    when i just wrote event.result then i got the below output. Please let me know why the problem is happening.

  4. Markuso Says:

    Ashish - This happens when you don’t include the Namespaces used with in the returned XML inside your flex code. Look at the code above again and you will notice that the Web Service has a name space declaration at this line:

    WebService(Namespace:="http://tempuri.org/SharePointService")

    So you must declare a namespace variable in your ActionScript 3 code as above:

    	private namespace ns1 = "http://tempuri.org/SharePointService";
    	private namespace ns2 = "http://tempuri.org/XMLSchema.xsd";
            use namespace ns1;
            use namespace ns2;
    

    The second name space is also needed as you will notice it is part of the full xml being returned from event.result value. So the answer to your question is make sure you have the exact namespaces declaration that tells Flex how to understand the data structure being read.

    Let me know if this was it for you please.

  5. Markuso Says:

    I have expanded on this demonstration to include how to add, delete, and update SharePoint data from within your Adobe Flex. I hope this gets you started to make more use of your SharePoint data within Flex.

  6. Ashish Says:

    Hi Markuso,
    I am writing code in C#. will it be enough that if I include
    “[WebService(Namespace:="http://tempuri.org/SharePointService")]” in .NET code and below namespaces in AS3 code?
    private namespace ns1 = “http://tempuri.org/SharePointService”;
    private namespace ns2 = “http://tempuri.org/XMLSchema.xsd”;
    use namespace ns1;
    use namespace ns2;

  7. Markuso Says:

    Ashish - Yes you got it. That is all you need to do in your C# code and AS3 code. The namespace can be whatever you like, as long as you match them up in your AS3 code. Always take a look at the full result you get back from the Web Service and analyze the namespaces that are being used. After that you make sure you tell you Flex application in AS3 to use those same namespaces so it can obtain the values within the XML.

  8. Ashish Says:

    Hi Markuso,

    Thanks for your reply. I was able to write successfully web service in C#.
    below is my code of AS3. In result function, data is available in alert statement, but data is not assigned to datagrid. Please help me in fixing the problem.

  9. Ashish Says:

    Thanks Markuso..I was able to get the data in a datagrid. Thanks for your quick replies and help. :)

  10. Markuso Says:

    That is wonderful Ashish. I didn’t get your code snippet with the comment you left so I can analyze for you, but I’m glad you were able to make it all work. Great job Ashish.

  11. spuky Says:

    Hi I am trying to get that working. I guess my Problem is on the Sharepoint side of things… sinc I had no idea on how to deploy your ASP.net webservice on my server I was folowing along the lines of the folowing article to build and deploy your code… http://msdn.microsoft.com/en-us/library/ms464040.aspx and it seems to be kind of working the WSDL is working an as long as I give It the wrong set of paramters. (I use soapUI) I get an error… but as soon as I give It the right paramters I get:
    soap:Server
    Die Anforderung konnte vom Server nicht verarbeitet werden. —> Fehler bei der Anforderung mit HTTP-Status 401: Unauthorized.
    which translates to
    “The request could not be handled by the Server —> Error with the Request: HTTP-Status 401: Unauthorized.”

    Any help with how to install and build the ASP.net service would be realy helpfull.

  12. Markuso Says:

    Spuky… First, your service and SharePoint must be on the same server to get access to the SharePoint data. If you are getting the Unauthorized message, then make sure that the user that is logged in, which is the one that has the browser open to the Flex app, has enough SharePoint permissions (Reader or Contributor rights) to the document library or list you are accessing.

    In most cases that is the reason you get the Unauthorized error. The service will use whatever permissions setup in SharePoint already to figure out if someone gets to see or update the data within.

  13. Vishnu Says:

    hi

    It would be gr8 if could able to send a WS method to update and Delete a List ITEM

    I am CF developer , no experience in .Net .

    Could you please send a a method for update and delete an list item?

  14. Ganesh Says:

    Hi All,

    I am facing a problem. VPN users are not able to get results from sharepoint webservice. It is not at all getting called through flex application (code). The same works when people are on network. Please suggest a solution or fix for this issue.

    Thanks,
    Ganesh

  15. Ganesh Says:

    Above scenario with VPN occurs few times and not always, which is annoying.

  16. Markuso Says:

    Hi Ganesh

    VPNs normally use https protocol to secure the connection, plus they hide the original URL to the resource with it’s own path when called. I would say try to make sure that your webservice is callable via https (SSL) protocol, then change your Flex code to call it through https and see what you get.

    Also, don’t forget to give access to the webservice’s URLs (http and https) through your VPNs security settings to the users.

    When a web app goes from https to http or vise versa, it asks the client if that is ok to do - but in Flex you want get that so it fails to connect to the resource in question.

    I use Charles debugging proxy http://www.charlesproxy.com/ to debug what the application is trying to connect to and as whom, and if there was any error messages that can lead to the problem. Try it. Good luck :)

  17. Ganesh Says:

    Hi Markuso,

    I found the problem. If I hard code webservice URL in Flex, then I am able to get expected results in either case (VPN or Network). The same doesn’t work when I read webservice URL from XML file. I feel the problem is because webservice through of flex gets invoked before I read webservice URL from xml file and sometimes after I read. That way it works sometime and doesn’t work most of the times. However, I tried getting webservice URL on Inizialize event and CreationComplete event and tried calling webservice after execution of get webservice URL.

    Still, I did not find solution.
    Please update on how to get webservice URL before webservice execution in Flex.
    In order to get correct results from webservice.

    Thanks,
    Ganesh

  18. Markuso Says:

    Hi Ganesh,

    Drop your initialize event and stick with your creationComplete as follows. What I do is always read my application custom settings XML file during the creationComplete stage, then in the result handler (return results) of the settings XML file call, I would use the returned webservice URL to set it to the webservice as I’m guaranteed that it is available to me in this result function. Lastly, I would invoke the webserivce right after I set its URL within this same result handler funtion. Try that order of execution as it always works for me.

    Markuso

  19. Tad Says:

    Hi Markuso,
    Great article for integrating Flex and SharePoint. I have a similar type problem that I wonder if you might shed some light on. I have a Flex application that connects to an Oracle database for metadata in the forms. Once all the metadata has been added it creates a new record number with the key being the facility, record number, addendum number and response number. I’d like to connect SharePoint to open a MS Word template that gets some of the template info from the Oracle database metadata and the remainder from user input into the template. I then need to save the document in SharePoint with the key number. Once saved, I need to be able to open it using the key data to add additional data or update with revised metadata and be resaved once again. Do you have any ideas for accomplishing something like this? Appreciate any help you can send my way.

    Thanks,
    Tad

  20. Ganesh Says:

    Hi Markuso,

    How and where should i create custom settings XML file in my application.
    At present, I don’t have such file in my project.
    The XML file I mentioned earlier was created by me in project folder and I was reading it through “mx:HTTPService”.

    Please advice.

    Thanks,
    Ganesh

  21. Markuso Says:

    @Tad, I can’t say that I have a solution to your application needs, but it looks to me that you will need to use your middle teir server technology (like .NET) to load the MS Word document and use Microsoft’s native classes to manipulated on the server side then save back to SharePoint. You will be interacting with SharePoint using its .NET API classes as they are native to .NET. Don’t do all of this process on the client side within your Flex interface. Maybe the trigger is from there, but the processing is done on the server technology.

  22. Markuso Says:

    @Ganesh, yes it is an XML file of your choosing. I normally create file named AppSettings.xml and place it in the root of the application. Then the very first thing I do in my init() function (which is called on the creationComplete event) is to call and load that file using the HTTPService call and save the values of the nodes into a custom appConfig object or just normal variables so I can use in my application and make decisions on them.

    So I place values into that XML file like my webservice WSDL URL setting, SharePoint lists IDs, etc. You can use any format of XML you like. Mine might look like this:

    <settings>
      <webserviceWsdl>http://thepath/to/my/web/service.asmx?WSDL</webserviceWsdl>
      <setting1>value</setting1>
      <sharepointLists>
        <listA>
          <url>http://server/sites/site/listA</url>
          <guid>0000-00000-000000-00000-000</guid>
         </listA>
        <listB>
          <url>http://server/sites/site/listB</url>
          <guid>1111-11111-111111-11111-111</guid>
         </listB>
      </sharepointLists>
      ...etc
    </settings>
  23. Ganesh Says:

    Markuso,

    Thanks for you detailed reply.
    I have one question. You mentioned in your reply that “I normally create file named AppSettings.xml and place it in the root of the application”. In my case, I am keeping the files .swf,.html etc from “bin-release” folder into sharepoint document library and accessing application through page viewer webpart on sharepoint. In my flex project, where should I keep the .xml file. Earlier, I did try putting .xml file in sharepoint document library folder and gave the path relative path in .mxml in httpservice. This did work, but result was not consistent. I got the issues, which I mentioned earlier.

    Please advice.

    Thanks,
    Ganesh

    You mentioned

  24. Ganesh Says:

    Markuso,

    I think, it will be helpful for me; if I would get an idea about your below response. I need a sample on below, because I was using a variable in mx:webservice and assinging values(from xml) to those in Httpservice result function, which doesn’t work sometime.

    Your earlier response:
    “In the result handler (return results) of the settings XML file call, I would use the returned webservice URL to set it to the webservice as I’m guaranteed that it is available to me in this result function. ”

    Please sent a sample on how to assign values to wsdl of mx:webservice in result of httpservice call.

    This will definately help. Awaiting for your response.

    Thanks,
    Ganesh

  25. Markuso Says:

    @Ganesh, take a look at this sample below and notice how I don’t call the webservice initially but I wait and call it on the HTTPService result handler:

    <mx:HTTPService id="appSettingsService" resultFormat="e4x" result="appSettingsServiceResult(event)"/>
     
    <mx:Script>
    	<![CDATA[
    		import mx.rpc.remoting.RemoteObject;
      		import mx.rpc.events.ResultEvent;
           	        import mx.rpc.events.FaultEvent;
     
    		[Bindable] public var appSettingsXML:XML;
     
    		private function init():void 
    		{
    			var now:Date = new Date();		    
    			//Append the time to prevent caching if you want
    			appSettingsService.url = "AppSettings.xml?" + now.time.toString(); 
    			appSettingsService.send();
    		}
     
        	private function appSettingsServiceResult(event:ResultEvent):void 
    		{
    			appSettingsXML = new XML(event.result);
    			myWebservice.wsdl = appSettingsXML.webserviceWsdl; //this is from the custom XML tree
     
    			//then start assigning the event listeners to methods and call them as needed
    			myWebservice.GetClientsList.addEventListener(ResultEvent.RESULT, getClientsListResult);
    			myWebserivce.GetClientsList();
        	      }
    	]]>
    </mx:Script>

    Of course the above is not complete code but it should give you an idea.

  26. Ganesh Says:

    Hi,

    Used “myWebservice.loadWSDL(webServiceUrl)” after “myWebservice.wsdl = appSettingsXML.webserviceWsdl”.

    It worked like a magic.
    Thanks to Markuso.

    Thanks,
    Ganesh

  27. Mack Says:

    Good day Markuso, I am having the same problem that Ganesh had with getting the results back into the dataXMList variable. I see the result when I debug the app and this is what I get:

    In my AS3 code I have the namespaces listed as:

    private namespace ns1 = “http://tempuri.org/”;
    private namespace ns2 = “http://tempuri.org/XMLSchema.xsd”;
    use namespace ns1;
    use namespace ns2;

    Any help you can provide would be GREATLY APPRECIATED ;0)

  28. Mack Says:

    I noticed that the code i inserted got stripped:
    GetSharePointListXMLResponse xmlns=”http://tempuri.org/” xmlns:soap=”http://schemas.xmlsoap.org/soap/envelope/” xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xmlns:xsd=”http://www.w3.org/2001/XMLSchema”

    GetSharePointListXMLResult
    listitems
    data ItemCount=”4″

  29. Markuso Says:

    @Mack - Try to play with this line:
    dataXMLList = new XMLListCollection(new XMLList(event.result.data.row));

    By changing the event.result.data.row to maybe event.result.listitems.data.row or as you see the hierarchy of the XML result in your debugging. The event.result always maps to the root node of the XML returned, then you just add the child node names up to what represents a row to you.

  30. Stu Says:

    Thank you for all your hard work. I found your articles very helpful.

    Like you, I found there was a problem accessing SharePoint data using direct calls to the Web Services. However, I discovered that if the Flex application is running within the SharePoint site, there is no such problem and I didn’t need a proxy to access the Web Services.

    I created a Flex 3 Web application and posted the compiled .swf file to a document library. Next, I created a SharePoint Page and added a Page Viewer Web Part and specified the url to point to the .swf file. To my amazement, it worked!

    I will next experiment with updates. I want to see how to avoid one user overlaying another’s data.

    -Stu

  31. Markuso Says:

    That is fantastic Stu. I thank you so much for sharing that with us all here :)

Leave a Reply

Copyright © 2007-2009 Markuso | WP Theme & Icons by N.Design Studio
Entries RSS Comments RSS Log in