ﻁ DevExpertise » WCF

DevExpertise

Practical tips and tricks for all things .NET, SharePoint, Silverlight, InfoPath, and general application development.

http://www.isg.rhul.ac.uk/akay/teaching/... viagra achat sans ordonnance
kamagra inde viagra generique hollande générique cialis meilleur prix faux viagra inde
http://www.soyons.fr/?page=33077&pi=3307... remboursement cialis
  • köpa viagra receptfritt viagra generico indiano viagra 100 mg
  • finasteride en ligne viagra kosten in der apotheke cialis requiere receta medica
    compro viagra economico cialis ohne rezept http://www.cerphi.net/?size=320158&price... achat viagra en ligne comparação dos pre em portugal cialis e viagra acquisto viagra cialis

    Retrieving SharePoint List Data from Silverlight Without a Custom WCF or ASP.NET Web Service

    Posted by DevExpert on 7th February 2009

    I’ve done a little work in the recent months with Silverlight, specifically with leveraging Silverlight inside of SharePoint.  My first project involved a pulling in data from SharePoint via a WCF service, and while it worked, it took a long time to configure correctly and to add the necessary components to SharePoint in order for it to work.  Sahil Malik describes a method beginning here, and as you can see it’s definitely doable but not the simplest approach.

    While creating a WCF will offer you the most power and flexibility when it comes to the data it can expose, as you can manipulate SharePoint data (or any data for that matter) any way you like.  In this post, I’m going to show you how to retrieve SharePoint list data in Silverlight the “old-fashioned” way – by using the out-of-the-box SharePoint web services, and executing an HttpWebRequest to get our data.

    Because there are a ton of different concepts I could elaborate on related to Silverlight and SharePoint, such as creating a web part host, configuring SharePoint for Silverlight, etc., for the sake of this post I’m going to keep it focused on the data retrieval only.  In future posts, I’ll dive into my approach for hosting a Silverlight app in SharePoint.  Also, take a look at this post from Karine Bosch – she has a very similar approach and hers is a lot prettier than mine!

    First, I defined the “Widgets” list I want to retrieve data from. In addition to the Title field, it contains a Description field and an Image field:image

    Next, I created a new Silverlight application in Visual Studio, and defined a Widget class, which will serve as the representation of a Widget list item:

    public class Widget {
        public string Title { get; set; }
        public string Description { get; set; }
        public string ImageUrl { get; set; }
    }

    I also added a few class-level variables in my Page.xaml.cs file, which I’ll use in my data methods:

    private List<Widget> _widgets = null;
    private Stream _body = null;
    private string _responseString;

    For the data retrieval, I’m going to be leveraging the out-of-the-box Lists.asmx web service to retrieve the list items, and build an HttpWebRequest object.  The BeginGetRequestStream method executes the request, and will asynchronously call the RequestCallback method when it finishes:

    private void GetData() {
        try {
            Uri listUri = new Uri("http://server/_vti_bin/Lists.asmx", UriKind.Absolute);
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(listUri);
    
            request.Method = "POST";
            request.ContentType = "application/soap+xml; charset=utf-8";
            request.Headers["ClientType"] = "Silverlight";
            request.BeginGetRequestStream(new AsyncCallback(RequestCallback), request);
        }
        catch (Exception ex) {
            HandleException(ex);
        }
    }

    Here’s where the real work needs to be done.  In our callback method, we need to build a SOAP envelope that will be passed to the web service in order to get a valid response.  If you’re uncertain where to find that envelope or are unsure if how it should be formatted, simply browse to the web service itself and click the method that you will be executing:

    image

    Once the SOAP envelope format is determined, simply add in the listName, viewName (if necessary), query, viewFields, and queryOptions, and you have your envelope.  The next step is to get the response by asynchronously executing the BeginGetResponse method and passing in the ResponseCallback callback method:

    private void RequestCallback(IAsyncResult asyncResult) {
        try {
            string envelope =
                @"<?xml version=""1.0"" encoding=""utf-8""?>
                    <soap12:Envelope
                     xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance""
                     xmlns:xsd=""http://www.w3.org/2001/XMLSchema""
                     xmlns:soap12=""http://www.w3.org/2003/05/soap-envelope"">
                        <soap12:Body>
                            <GetListItems xmlns=""http://schemas.microsoft.com/sharepoint/soap/"">
                                <listName>Widgets</listName>
                                <query>
                                    <Query xmlns="""">
                                        <OrderBy>
                                            <FieldRef Name=""Title"" />
                                        </OrderBy>
                                    </Query>
                                </query>
                                <viewFields>
                                    <ViewFields xmlns="""">
                                        <FieldRef Name=""Title"" />
                                        <FieldRef Name=""Description"" />
                                        <FieldRef Name=""Image"" />
                                    </ViewFields>
                                </viewFields>
                                <queryOptions>
                                    <QueryOptions xmlns="""">
                                        <IncludeMandatoryColumns>False</IncludeMandatoryColumns>
                                    </QueryOptions>
                                </queryOptions>
                            </GetListItems>
                        </soap12:Body>
                    </soap12:Envelope>";
    
            UTF8Encoding encoding = new UTF8Encoding();
            HttpWebRequest request = (HttpWebRequest)asyncResult.AsyncState;
            _body = request.EndGetRequestStream(asyncResult);
            envelope = string.Format(envelope, _listName);
            byte[] formBytes = encoding.GetBytes(envelope);
    
            _body.Write(formBytes, 0, formBytes.Length);
            _body.Close();
    
            request.BeginGetResponse(new AsyncCallback(ResponseCallback), request);
        }
        catch (WebException ex) {
            HandleException(ex);
        }
    }

    The ResponseCallback method is responsible for determining that the response is valid, and to get the data out of the response.  Once the data is retrieved from the response stream, the only step left is to process that data, and for that we call ProcessResponse.  We must use the BeginInvoke() method of the page’s Dispatcher object, because all of the data retrieval is done asynchronously on a different thread.  Since you can’t modify controls on a different thread than the one it was created on, we have to invoke it this way and let Silverlight handle the thread marshalling:

    private void ResponseCallback(IAsyncResult asyncResult) {
        HttpWebRequest request = (HttpWebRequest)asyncResult.AsyncState;
        HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asyncResult);
        Stream content = response.GetResponseStream();
    
        if (request != null && response != null) {
            if (response.StatusCode == HttpStatusCode.OK) {
                _widgets = new List<Widget>();
    
                using (StreamReader reader = new StreamReader(content)) {
                    _responseString = reader.ReadToEnd();
                    reader.Close();
                }
    
                try {
    
                    this.Dispatcher.BeginInvoke(ProcessResponse);
    
                }
                catch (WebException ex) {
                    HandleException(ex);
                }
            }
        }
    }

    And finally, the ProcessResponse method that parses the response data and creates are Widgets collection, which is then set as the page’s DataContext:

    private void ProcessResponse() {
        XDocument results = XDocument.Parse(_responseString);
    
        _widgets = (from item in results.Descendants(XName.Get("row", "#RowsetSchema"))
                    select new Widget() {
                        Title = item.Attribute("ows_Title").Value,
                        Description = item.Attribute("ows_Description").Value
                        ImageUrl = FormatImageUrl(item.Attribute("ows_Image").Value),
                    }).ToList();
    
        this.DataContext = _widgets;
    }
    
    private string FormatImageUrl(string value) {
        return value.Substring(0, value.IndexOf(','));
    }

    Now that we have our data, creating a snazzy Silverlight web part is only limited by your creativity and XAML-slinging skills.  Here’s a quick and dirty snippet to verify we’re actually getting data:

    <UserControl x:Class="DevExpertise.Silverlight.App.Page"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
        <StackPanel>
            <Grid x:Name="LayoutRoot" Background="White">
                <ListBox ItemsSource="{Binding}" VerticalAlignment="Stretch">
                    <ListBox.ItemTemplate>
                        <DataTemplate>
                            <Grid>
                                <StackPanel Orientation="Horizontal">
                                    <Image Source="{Binding ImageUrl}" Height="40" />
                                    <StackPanel>
                                        <TextBlock Text="{Binding Title}" FontWeight="Bold" />
                                        <TextBlock Text="{Binding Description}" />
                                    </StackPanel>
                                </StackPanel>
                            </Grid>
                        </DataTemplate>
                    </ListBox.ItemTemplate>
                </ListBox>
            </Grid>
        </StackPanel>
    </UserControl>

    …and voila!  Silverlight in SharePoint consuming list data:

    image

    That’s all it takes to get data from SharePoint without using a custom web service or having to go through the hassle of building and deploying a WCF service.  In a future post, I’ll describe how to build a generic and reusable web part to host Silverlight applications.  Stay tuned!

    Tags: , , , , ,
    Posted in .NET, SharePoint, Silverlight, XAML | 9 Comments »