다음을 통해 공유


Beginning SharePoint 2010 Development: Chapter 10: Developing Service-Oriented Applications for SharePoint 2010

Summary: This chapter discusses web services that are native to SharePoint 2010, building custom web services (Microsoft ASP.NET, Windows Communication Foundation (WCF), REST, and Azure services), and implementing custom web services by using different client solutions in SharePoint 2010.

Applies to: Business Connectivity Services | SharePoint Foundation 2010 | SharePoint Server 2010 | Visual Studio

This article is an excerpt from Beginning SharePoint 2010 Development by Steve Fox from Wrox Press (ISBN 978-0-470-58463-7, copyright © 2010 by Wrox, all rights reserved). No part of these chapters may be reproduced, stored in a retrieval system, or transmitted in any form or by any means—electronic, electrostatic, mechanical, photocopying, recording, or otherwise—without the prior written permission of the publisher, except in the case of brief quotations embodied in critical articles or reviews.

Contents

  • Introduction

  • ASP.NET Web Services

  • Windows Communication Foundation (WCF) Web Services

  • RESTful Web Services

  • Azure and SharePoint

  • Summary

  • Recommended Reading

  • About the Author

Click to grab code  Download code

Introduction

One of the key innovations in the software industry over the past few years has been the growing use of Web services to integrate systems. One of the key undercurrents of this book is that SharePoint 2010 is a platform, and, since it is a platform, it is imperative that you be able to interoperate with Web services.

This chapter is not the first time you're seeing the use of services. For example, in Chapter 5, you saw how to use Web services to interact with a SharePoint list, and, in Chapter 8, you saw BCS solutions that leveraged Web services. However, this chapter is a concerted look at both native and custom Web services, and how you can develop custom solutions that integrate with SharePoint.

Web services enable you to develop applications that can expose or reach out to systems or application programming interfaces (APIs) mediated either by a network or by the Internet. One of the primary benefits of Web services is that they can bridge heterogeneous systems — those systems that, without these services, might exist in isolation. The Web services can be restricted to an enterprise network (for example, multiple applications accessing an Expenses Web service to submit expenses to a common remote SAP system), or you can leverage Web services that can bridge systems across the Internet (for example, accessing stock Web services or weather services).

In Web service parlance, you typically have a client and a server when consuming a service. The server is where the Web service is built and deployed to (for example, Windows Server 2008 R2). The client is the application that consumes the exposed Web service. (A typical client application within SharePoint could be a Silverlight application or Web part.) It is also very common for Windows, Windows Presentation Foundation (WPF), or even Microsoft Office applications to leverage Web services to interact with SharePoint.

Within this architecture, you will also require something that hosts the Web service, such as Internet Information Services (IIS). In Figure 10-1, note that the client can leverage a number of different service proxies/connections in SharePoint 2010 and subsequently integrate with different types of systems or applications (such as enterprise services, Web 2.0 social services, and even custom Azure services).

Figure 1. Service architecture

Service architecture

Web services communicate across the client and the server in a couple of different ways. Using the Hypertext Transfer Protocol (HTTP), you can build services using the Simple Object Access Protocol (SOAP) and Web Services Description Language (WSDL) standards — you'll find that these are the standards that the native SharePoint Web services use. Characteristic of SOAP standards is the passing of XML messages from client to server — for example, a Web service will send back a data packet that is well-formed XML as a return data object.

Beyond Web services that use SOAP, you can also build Representational State Transfer (REST) Web services. RESTful Web services are "lightweight" services (or, more accurately, protocols) that enable you to GET, PUT, POST, or DELETE using HTTP methods. RESTful services do not require the WSDL service-level definitions and often integrate much better into the Web browser experience.

In SharePoint 2007, there were a number of constraints when it came to building Web services. Many of these constraints go away in SharePoint 2010. For example, Windows Communication Foundation (WCF) — a newer type of Web service that was introduced in .NET 3.0 — is supported natively, as is REST. Furthermore, you also get the capability to build and deploy custom ASP.NET services to SharePoint, or leverage the native ASP.NET Web services that ship with SharePoint. You can very easily integrate custom services into SharePoint as well. What this means for developers is that you have an abundance of options when developing service-based applications.

Although this chapter does not provide a comprehensive backdrop regarding the history and evolution of Web services, it does equip you with a fundamental treatment of Web services as they are supported in SharePoint 2010. With this in mind, this chapter covers four major areas:

  • ASP.NET Web services — Ironically, many developers consider these services legacy. But you'll find a wealthof native ASP.NET services in SharePoint 2010, and building ASP.NET Web services is a straightforward proposition.

  • RESTful services — You saw these in Chapter 5, but you'll see them in a different light in this chapter (programming against Excel on the server).

  • Windows Communication Foundation (WCF) — Lately, this has been a more common way to build and deploy Web services, given the tighter control that developers have over many elements of the service development and deployment process (for example, security and binding).

  • Cloud computing — SharePoint 2010 is aligned with the cloud computing evolution (given SharePoint Online and its capability to host custom code through sandboxed solutions); thus, you'll see a new cloud platform, called Azure, discussed in the context of SharePoint 2010.

ASP.NET Web Services

ASP.NET Web services are native to SharePoint 2010. A number of useful services ship out of the box (native), and you can very easily build and deploy ASP.NET Web services either into the SharePoint root, or to IIS. In this section, you'll see coverage of both the native Web services and custom Web services — and how you can leverage both to build your solutions for SharePoint 2010.

As discussed earlier, one of the core characteristics of ASP.NET Web services is the use of the SOAP and WSDL standards. For SharePoint, this means that when you call an ASP.NET Web service, the data package (or payload) will be passed across the service using these standards. The XML structure is accessible through a couple of ways.

The first is through the use of Collaborative Application Markup Language (CAML), with which you can issue queries against a service call to, for example, a SharePoint list. You saw this in Chapter 5.

Another way to interact with the data occurs when extracting the data from the XML payload. You use XLinq structures (for example, the XDocument object) to get the data into a format you can query. Because data programmability is now both strongly and loosely typed in SharePoint, you can manage queries against the data using the XDocument object, or you can use Language Integrated Query (LINQ) queries to query and manage the data.

Beyond XML payloads, the WCF Data Services enable you to treat SharePoint data as strongly typed objects. You also saw this in Chapter 5 where REST was used to view and update list data.

Note

Another pattern you've seen in this book is the use of custom objects (for example, classes) and the use of List collections, which are IEnumerable objects that allow you to query and easily bind your resulting queries to controls such as datagrids and listboxes.

There are many different types of Web services that are native to SharePoint 2010. These services cut across supporting List interaction, authentication, Excel Services, meetings management, and so on. To review the full set of services that ship with SharePoint, navigate to c:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\ISAPI. All of the ASP.NET Web services end with the .asmx file extension. You can also open each of these services in the browser by typing http://<server name>/_vti_bin/<Web Service Name>.asmx and then browse the different Web methods that each service offers.

To get more information on SharePoint 2010 class libraries and Web services, go to SharePoint Server 2010 Class Libraries and Web Service References.

Let's first take a look at a native Web service example and then move on to discussing custom ASP.NET Web services.

Native Web Service

As mentioned earlier, there are many different ASP.NET Web services available for you to use when building your SharePoint solutions. There are also a number of amendments to the Web services in SharePoint 2010. Those who are returning to SharePoint 2010 development from SharePoint 2007 may need to test some of the code they built with the SharePoint 2007 Web services to ensure there is no broken code. For the most part, though, you should find a relatively seamless upgrade path from 2007 to 2010.

There are two types of services in SharePoint. The first enables you to access administrative capabilities. A set of non-administrative services is also available. To access the SharePoint Web services, you use the following URL syntax: http://<site>/_vti_bin/<Web Service Name>.asmx (for example, http://intranet.contoso.com/\_vti\_bin/socialdataservice.asmx). Note that if you're accessing administrative services, you will need to add the port number, because you would not be accessing the default port 80 (for example, http://intranet.contoso.com:8080/\_vti\_bin/diagnostics.asmx).

There are many new service capabilities that are built into SharePoint 2010. These capabilities range from new administrative services such as Diagnostics (a service for managing client reports) to more social-centric services such as SocialDataService (a service to manage social features).

Although there are many more services that you can leverage within SharePoint 2010, let's walk through one example to show you how you can use a service to build a service-oriented solution for SharePoint using the SocialDataService Web service (that is, http://<server>/_vti_bin/socialdataservice.asmx). As a part of the growing support for more social-centric applications, this Web service enables you to work with social metadata such as tags and terms, and insert comments, among other activities that are central to building social applications.

Note

For more information about the Web services that are available in SharePoint 2010, see SharePoint Server 2010 Class Libraries and Web Service References.

Before you walk through the following example, create three different wiki sites in your SharePoint site collection, and then rate each of the sites by using the wiki Rating feature. You'll need the URLs of these three wiki sites for this walkthrough.

Try It Out: Leveraging the Social Data Web Service

Tip

Code file (SocialRatingWebPart.zip) available for download at Wrox.com.

The Social Data Web service provides rich access to a number of key social APIs in SharePoint.

To use the Social Data Web service in an application

  1. Open Visual Studio 2010 and click File, choose New, and then click Project.

  2. Select Empty SharePoint Project. Provide a name for your application (for example, SocialRatingWebPart), and then click OK. When prompted, select Deploy as farm solution and then click Finish.

  3. When Visual Studio creates the project, right-click the project, click Add, and then choose New Item. In the SharePoint 2010 project node, select Visual Web Part. Provide a name for the Web part (for example, SocialRatingData) and then click Add.

  4. Right-click the .ascx file and select View Designer. Click the Source tab, and then add the following bolded code to the ascx code behind.

    <%@ Assembly Name="$SharePoint.Project.AssemblyFullName$" %>
    <%@ Assembly Name="Microsoft.Web.CommandUI, Version=14.0.0.0, Culture=neutral,
        PublicKeyToken=71e9bce111e9429c" %>
    <%@ Register Tagprefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls"
        Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral,
        PublicKeyToken=71e9bce111e9429c" %>
    <%@ Register Tagprefix="Utilities" Namespace="Microsoft.SharePoint.Utilities"
        Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral,
        PublicKeyToken=71e9bce111e9429c" %>
    <%@ Register Tagprefix="asp" Namespace="System.Web.UI" Assembly=
        "System.Web.Extensions, Version=3.5.0.0, Culture=neutral,
        PublicKeyToken=31bf3856ad364e35" %>
    <%@ Import Namespace="Microsoft.SharePoint" %>
    <%@ Register Tagprefix="WebPartPages" Namespace="Microsoft.SharePoint.WebPartPages"
        Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral,
        PublicKeyToken=71e9bce111e9429c" %>
    <%@ Control Language="C#" AutoEventWireup="true"
        CodeBehind="SocialRatingDataUserControl.ascx.cs" Inherits=
        "SocialRatingWebPart.SocialRatingData.SocialRatingDataUserControl" %><
    asp:UpdatePanel ID="RatingUpdatePanel" runat="server"><ContentTemplate><asp:Label ID="lblSocialRatingTitle" runat="server" Font-Bold="True"ForeColor="#000066" Text="Wiki Rating Data"></asp:Label><table><tr><td><asp:Label ID="lblRatingDataList" runat="server" ForeColor="#000066"Text="Rating Data"></asp:Label></td><td><asp:ListBox ID="lstbxRatingData" runat="server" Width="172px"></asp:ListBox></td></tr><tr><td><asp:Label ID="lblRating" ForeColor="#000066" runat="server"Text="Avg. Rating:"></asp:Label></td><td><asp:Label ID="lblData" ForeColor="#000066" runat="server"Text="Data"></asp:Label></td></tr></table><table><tr><td><asp:Button ID="btnRefresh" runat="server" Text="Refresh"ToolTip="Click to refresh." onclick="btnRefresh_Click" /></td><td></td></tr></table></ContentTemplate></asp:UpdatePanel>
    
  5. Right-click the References node and select Add Service Reference.

  6. Click the Advanced button, and then click Add Web Reference. Type the following URL into the URL field (making sure you replace the server name with your SharePoint server,such as http://fabrikamhockey/_vti_bin/socialdataservice.asmx).

    http://<server name>/_vti_bin/socialdataservice.asmx.

  7. Click the Design tab to switch into the Designer view and then double-click the btnRefresh button.

  8. When the code behind opens, add the following bolded code to the code behind.

    using System;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Web.UI.WebControls.WebParts;
    using SocialRatingWebPart.SocialWS;
    
    namespace SocialRatingWebPart.SocialRatingData
    {
    
      public partial class SocialRatingDataUserControl : UserControl
      {
        protected void Page_Load(object sender, EventArgs e)
        {
        }
        protected void btnRefresh_Click(object sender, EventArgs e)
        {
          // Add the URLs for your three wiki sites here.
          string ratingonConfURL = "http://intranet.contoso.com/conf/Pages/Home.aspx";string ratingonProjURL = "http://intranet.contoso.com/projects/Pages/Home.aspx";string ratingonPlansURL = "http://intranet.contoso.com/plans/Pages/Home.aspx";SocialDataService mySocialDataService = new SocialDataService();mySocialDataService.Credentials =System.Net.CredentialCache.DefaultCredentials;mySocialDataService.Url = "http://intranet.contoso.com/_vti_bin/socialdataservice.asmx";SocialRatingDetail confWikiRating =mySocialDataService.GetRatingOnUrl(ratingonConfURL);SocialRatingDetail projWikiRating =mySocialDataService.GetRatingOnUrl(ratingonProjURL);SocialRatingDetail plansWikiRating =mySocialDataService.GetRatingOnUrl(ratingonPlansURL);addRatingsToWebPart(confWikiRating.Rating,projWikiRating.Rating, plansWikiRating.Rating);mySocialDataService.Dispose();}private void addRatingsToWebPart(int confRate, int projRate, int plansRate)    {int avgRating = 0;string confWiki = "Conference Wiki: " + confRate.ToString();string projWiki = "Project Wiki: " + projRate.ToString();string plansWiki = "Plans Wiki: " + plansRate.ToString();avgRating = (confRate + projRate + plansRate) / 3;string avgRatingForWikis = "Average Rating: " + avgRating.ToString();lstbxRatingData.Items.Add(confWiki);lstbxRatingData.Items.Add(projWiki);lstbxRatingData.Items.Add(plansWiki);lstbxRatingData.Items.Add(avgRatingForWikis);lblData.Text = avgRating.ToString();    }
    
      }
    }
    
  9. Amend the .webpart file so that it has a more intuitive title and description, similar to the following example.

    …
      <properties>
        <property name="Title" type="string">Wiki Rating Web Part</property>
        <property name="Description" type="string">Web Part that displays
          wiki rating data.</property>
      </properties>
    …
    
  10. Press F6 to build the project. When the project successfully builds, click Build, and then choose Deploy Solution to deploy the new Visual Web part to SharePoint.

  11. Navigate to your SharePoint site. Create a new Web part page and then click Add a new web part.

  12. In the Custom category, select your newly created Web part and then click Add. When the Web part is added to the page, click the Refresh button. You should see the social data service load information into the Web part, as shown in Figure 2.

    Figure 2. Wiki Rating Web part

    Wiki Rating Web part

    How it works

    The Social Data Web service provides a set of Web methods to interact with SharePoint social data. Note that your first step in using the Web service was creating a proxy, and setting the credentials and endpoint for the service proxy. In this example, you used the GetRatingOnURL method to extract the ratings you'd given your three wiki sites by passing the string URL in with the method call.

    SocialRatingDetail confWikiRating = mySocialDataService.
      GetRatingOnUrl(ratingonConfURL);
        SocialRatingDetail projWikiRating = mySocialDataService.
      GetRatingOnUrl(ratingonProjURL);
        SocialRatingDetail plansWikiRating = mySocialDataService.
          GetRatingOnUrl(ratingonPlansURL);
    

    You also created a helper function to calculate the average ratings for the three different wikis, and passed it the Rating property, which is the property that is returned from the call to the GetratingOnURL method. Note that you recast the Rating properties into integer values before you calculated the average. After you calculated the average rating using the three, you added the information to a list box (lstbxRatingData) and set the Text property of a label (lblData) so that it would contain the rating.

Custom ASP .NET Services

As a general practice, just as you should generally use the server-side object model for server-side applications, you should equally leverage the services that ship with SharePoint 2010 when designing service-based applications for SharePoint. This is because you don't want to re-create the wheel, so to speak, and it's much easier for you to use the services that SharePoint natively understands. However, there may be times when you want to create your own custom ASP.NET service. For example, you may want to integrate Enterprise Resource Planning (ERP) data from disparate systems, or you may need to create a connection to a legacy data in SQL. The end goal, therefore, would be to surface this data in SharePoint. This is also very possible. Let's take a look at an example.

The example that you'll build is a custom Web service that retrieves data from a SQL database. It is a straightforward Web service that illustrates how you can build a custom ASP.NET Web service and then deploy it to IIS. In addition, the example leverages the Business Connectivity Services (BCS), one of the core new capabilities that is built into SharePoint 2010. You learned about this in Chapter 8. However, in this example, you use the BDC Metadata project template in Visual Studio 2010 to call the service.

Try It Out: Integrating a custom ASP.NET Service with BCS

The BDC Metadata model is a great way to model external data and create an external list using the new BCS in SharePoint 2010. Creating a model is equally compelling when you use a Web service to integrate external data from SharePoint into the external list.

To create an external list using a custom Web service

  1. Create a new SQL Server database called Sales. To create the database, open SQL Server 2008 (or 2005) and right-click the Database node. Select New Database. In design view, create five columns, as shown in Figure 3.

    Figure 3. Creating columns in SQL Server

    Creating columns in SQL Server

  2. After you create the database, save it with the name Sales, and then add some sample data to the table, as shown in Figure 4.

    Figure 4. Sample sales data

    Sample sales data

  3. With the database complete, open Visual Studio 2010. Click File and then choose New. Select the Web category. Within the Web category, select ASP.NET Web Service. Provide a name for your service, and then click OK.

  4. Click Data and then choose New Data Source. In the Data options, select Data Model and then click OK.

  5. In the Data Connection Wizard, select New Connection.

  6. When prompted in the Data Connection Wizard, provide your server-name information, and then click the Sales database that you just created. Select the table that you created in the wizard, and then click Finish.

  7. Visual Studio adds the new entity data model from your database to the solution, which you can then use in your service.

  8. Before you start working with the service code, you need to add a custom object. Right-click the project, select Add, and then choose Class. Call the new class SalesObject, and then add the following bolded code to the newly added class. Note that, because you allowed nulls in your database, you must add a '?' when you declare each of the class variables.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    
    namespace MySalesService
    {
      public class SalesObject
    
      {
        public int companyID { get; set; }public string companyName { get; set; }public int? fy08Sales { get; set; }public int? fy09Sales { get; set; }public int? fy10Sales { get; set; }
      }
    }
    
  9. Right-click the Service.cs file and select View Code. Replace the existing Hello World service code with the following bolded code in the Service.cs file. This will be the core code that executes when your service is called.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Services;
    
    namespace MySalesService
    {
      [WebService(Namespace = "http://tempuri.org/")]
      [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
      [System.ComponentModel.ToolboxItem(false)]
    
      public class Service1 : System.Web.Services.WebService
      {
        SalesEntities mySalesData = new SalesEntities();List<SalesObject> mySalesList = new List<SalesObject>();[WebMethod]public List<SalesObject> getAllSalesData(){var returnSalesData = (from sales in mySalesData.Sales_Dataselect sales).ToArray();foreach (var s in returnSalesData){SalesObject tempSales = new SalesObject();tempSales.companyID = s.CompanyID;tempSales.companyName = s.CompanyName.ToString();tempSales.fy08Sales = s.FY08Sales;tempSales.fy09Sales = s.FY09Sales;tempSales.fy10Sales = s.FY10Sales;mySalesList.Add(tempSales);};return mySalesList;}[WebMethod]public string[] getSpecificSale(int companyID){string[] mySalesInfo = new string[5];var returnSpecificSalesItem = (from sales in mySalesData.Sales_Data.Where(x => x.CompanyID == companyID)select sales);foreach (var s in returnSpecificSalesItem){mySalesInfo[0] = s.CompanyID.ToString();mySalesInfo[1] = s.CompanyName.ToString();mySalesInfo[2] = s.FY08Sales.ToString();mySalesInfo[3] = s.FY09Sales.ToString();mySalesInfo[4] = s.FY10Sales.ToString();}return mySalesInfo;    }  }
    
    }
    
  10. Press F5 to test the service code.

  11. You should now be able to click each of the Web methods in your new service to execute the code, as shown in Figure 5. The code will retrieve all of the items (getAllSalesItems), or get one item if you enter an ID (getSpecificSale). Test both of the methods to ensure that they work.

    Figure 5. Web service page

    Web service page

  12. To deploy the service, create a new folder on your local drive using a name that you'll remember (for example, SalesService). Then, right-click the Web service project and select Publish. Select the Local File System option, navigate to the newly created folder, and then click Publish. You are now ready to create a new Web site in IIS that uses the published Web service to this folder.

  13. Open IIS and navigate to the Sites folder. Right-click the Sites node and select New Web Site. Provide a name for the site (for example, SPWebService). Navigate to the new folder that you created in Step 12 to map a virtual directory to the new Web site.

  14. To test the service, use a local account. Click Connections and then choose Use Custom Account. Provide a local system account that has system-wide access to the machine and SQL Server (for example, administrator). Click Test Connection to ensure that you are successfully authenticated when calling the service. (Note that when you deploy the service, you would use another type of account that is set up by your administrator and that enables applications or users to call this service within a specific security protocol.)

  15. After you configure the security, click the Content tab, right-click the Service1.asmx file and then select Browse. You should see the same service definition page that you did when you tested your service in Visual Studio. However, the URL may be different. This is the URL you will use when you implement the service. Test the service Web methods to ensure that they work properly.

  16. Now that you've created, tested, and deployed your Web service to IIS, you are ready to consume the custom ASP.NET Web service in a SharePoint application. Open Visual Studio, click File, choose New Project, and select the SharePoint 2010 node. In the SharePoint 2010 node, select the BDC Metadata Model project template. Provide a name (for example, SalesBDCModel), and then click OK.

  17. Visual Studio will create a new project for you with a number of default objects in the solution. The goal for using this project will be to model an external list (that uses BCS) by using the custom Web service and then deploy the service to SharePoint as an external list.

  18. Right-click the Entity1.cs file, and select View Code. Using the following bolded code, amend the Entity1 class to map to the data structure from your database.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    namespace SalesBDCModel.BdcModel1
    {
      public partial class Entity1
      {
        public int Identifier1 { get; set; }
        public string bdcCompanyName { get; set; }public int bdcFY08Sales { get; set; }public int bdcFY09Sales { get; set; }public int bdcFY10Sales { get; set; }
      }
    }
    
  19. After you finish, amend the Entity1Service code, which executesthe methods for your external list. For example, the ReadItem method uses the id parameter to load a specific list item, and the ReadList method loads all of the list items. The goal, though, is for you to load a specific item or list of items using the custom ASP.NET service. Amend the Entity1Service.cs file with the following bolded code.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using SalesBDCModel.SPSalesWebService;
    
    namespace SalesBDCModel.BdcModel1
    {
    
      public class Entity1Service
      {
        public static Entity1 ReadItem(int id){SPSalesWebService.Service1 myWSProxy = new Service1();string[] returnedData = new string[5];returnedData = myWSProxy.getSpecificSale(id).ToArray();Entity1 entity1 = new Entity1();entity1.Identifier1 = id;entity1.bdcCompanyName = returnedData[1];entity1.bdcFY08Sales = Int32.Parse(returnedData[2]);entity1.bdcFY09Sales = Int32.Parse(returnedData[3]);entity1.bdcFY10Sales = Int32.Parse(returnedData[4]);myWSProxy.Dispose();return entity1;}public static List<Entity1> ReadList(){List<Entity1> mySalesInfoList = new List<Entity1>();SPSalesWebService.Service1 myWSProxy = new Service1();var salesData = myWSProxy.getAllSalesData();foreach (var item in salesData){Entity1 tempEntity = new Entity1();tempEntity.Identifier1 = item.companyID;tempEntity.bdcCompanyName = item.companyName.ToString();tempEntity.bdcFY08Sales = item.fy08Sales;tempEntity.bdcFY09Sales = item.fy09Sales;tempEntity.bdcFY10Sales = item.fy10Sales;mySalesInfoList.Add(tempEntity);}myWSProxy.Dispose();return mySalesInfoList;}
    
      }
    
    }
    
  20. The final step in this custom solution is to ensure that the BDC model (the .bdml file) maps to the data that will be returned from the Web service call — essentially the properties in the Entity1object. To do this, double-click the BDC Explorer in the Solution Explorer and then amend the TyepDescriptors (think of these as the individual data elements within your model — for example, Identifier1, bdcCompanyName, and so on) within the BDC model under the Entity1 node.

    Specifically, ensure that, under the ReadItem node, the id includes a TypeDescriptor called Identifier1 (System.Int32), and the Entity1 node under the returnParameter node includes bdcCompanyName (System.String), bdcFY08Sales (System.Int32), bdcFY09Sales (System.Int32), bdcFY10Sales (System.Int32), and Identifer1 (System.Int32). Table 1 summarizes the TypeDescriptors and type names for the ReadItem method.

    Table 1. TypeDescriptor and Type Name

    TypeDescriptor

    Type Name

    Identifer1 (id)

    System.Int32

    bdcCompanyName (Entity1)

    System.String

    FY08Sales (Entity1)

    System.Int32

    FY09Sales (Entity1)

    System.Int32

    FY10Sales (Entity1)

    System.Int32

    Identifier1 (Entity1)

    System.Int32

    Then, under the ReadList node, ensure that the Entity1 node (under the EntityList and returnParameter nodes) includes the same TypeDescriptors as you had under the returnParameter in the ReadItem method. In fact, you can copy and paste the Entity1 node from the ReadItem method to the ReadList method. Table 2 summarizes the TypeDescriptors and type names for the ReadList method.

    Table 2. TypeDescriptor and Type Name

    TypeDescriptor

    Type Name

    bdcCompanyName (Entity1)

    System.System

    FY08Sales (Entity1)

    System.Int32

    FY09Sales (Entity1)

    System.Int32

    FY10Sales (Entity1)

    System.Int32

    Identifier1 (Entity1)

    System.Int32

    After you finish amending the structure of the BDC model, it should look similar to Figure 6. It is important that you model these correctly or else the external list will not be created properly because the data and data types will be incorrectly mapped.

    Figure 6. Amending the BDC Explorer

    Amending the BDC Explorer

  21. You can now save and build your project. After the project successfully builds, click Build, and then click Deploy to deploy the new external list to SharePoint.

  22. After it is deployed, open SharePoint and click Site Actions and then click View All Site Content.

  23. Click Create, choose Lists, and then select External List. Click Create and then provide a name and description. Because Visual Studio deployed the BDC Metadata model to SharePoint, you can click Browse and then select the model that you just deployed to SharePoint. When finished, click OK.

  24. By default, SharePoint opens the external list after you click OK, as shown in Figure 7.

    Figure 7. External list using the Web service

    External list using the Web service

How it works

In this walkthrough, you did a number of things. First, you created your data object (that is, the Sales database in SQL Server). Second, you created a service to interact with that data in two ways: to get all of the data and to get a specific item within the table. To accomplish this, you created a method called getAllSalesData and another method called getSpecificSale.

The first method returned a List collection (mySalesList) of a custom object that you created (SalesObject). The second method used an integer input parameter (companyID) as a filter to find the specific record within the database and then converted that to an array (mySalesInfo) to return to any client application.

After you finished creating the service, you deployed the service to IIS by creating a Web site in IIS and pointing the virtual directory of the Web site to the published Web service. Lastly, you created a SharePoint application that then called the Web service to populate an external list and display one of the records.

When the external list loads, it is calling the ReadList method, which, in turn, calls your Web service and loads the data from the external data system (in this case, it was SQL Server). If you click a particular item, this calls the ReadItem method and retrieves the specific list item using the id (which is the Identifier1 column).

The walkthrough was an advanced example of how you can integrate Web services with BCS. However, this is a very powerful integration, because, once you get the external data into your external list, you can then use the SharePoint client object model to further interact with that data. This means creating dynamic Silverlight applications, for example, against the external list that leverages the custom Web service.

Windows Communication Foundation (WCF) Web Services

WCF is another type of Web service that is supported in SharePoint 2010. Used more frequently these days, WCF was designed to a set of standards that enables developers to build service-oriented applications to support distributed computing.

WCF follows architectural principles similar to those of ASP.NET Web services — that is, there is a client and server, and the service is hosted. Client applications can consume one or more WCF services, and services will typically have a WSDL interface. WCF also implements a number of more advanced service standards, such as WS-Addressing, WS-Security, and WS-ReliableMessaging — which makes it a more robust, flexible, and secure option than its ASP.NET counterpart.

A WCF service has the following main parts:

  • A service class, which is the core code that executes the service.

  • The hosting mechanism.

  • The endpoint to the service to which the client application will connect.

The endpoints specify a contract that defines the methods of the service class. They also define a binding that specifies how a client will communicate with the service, and the address where the endpoint is hosted. Thus, while a service in WCF may (from an execution perspective) perform the exact same function as its ASP.NET counterpart, there are a number of syntactical and structural differences between them that make them slightly more complex to write, but, overall, more robust, flexible, and secure.

One of the key innovations in SharePoint 2010 is that it offers native support for WCF. This means that you can either deploy a custom WCF service to IIS, or you can deploy it into the SharePoint root. You should note that you can also self-host WCF services using the ServiceHost class. When a client application connects to the hosted WCF service, it does so using the endpoint that is defined within the service — essentially a URL specifying where the methods of the service can be accessed.

Note

For more general information on WCF, see Windows Communication Foundation on MSDN.

SharePoint 2010 offers a number of new WCF services. For example, one WCF service that was discussed earlier in the book was the Listdata.svc service — a WCF service that provides WCF Data Services–based interaction with list data. There have also been some other additions to SharePoint, including administrative services (BdcAdminService.svc), BDC services (BdcRemoteExecutionService.svc and BDCResolverPickerService.svc), and other storage, client accessibility, and security services (for example, CellStorage.svc, Client.svc, and spclaimproviderwebservice.svc). (For more information about SharePoint 2010 class libraries and Web services, see SharePoint Server 2010 Class Libraries and Web Service References.)

Of specific interest in this section is the use of custom WCF services for SharePoint 2010. To illustrate how you can create and implement a WCF service, you will leverage the database you created earlier in the chapter and build a WCF service that reads and writes data to the SQL database using a custom WCF service.

Try It Out: Integrating a Custom WCF Service with SharePoint

Tip

Code files (GetSPSalesRecord.zip and AddSalesRecordWebPart.zip) available for download at Wrox.com.

You can use WCF services in many different ways.

To create a custom WCF service and leverage it in SharePoint

  1. Open Visual Studio 2010, click File and choose New. Under WCF, click WCF Service Application. Provide a name for the project (for example, GetSPSalesData), and then click OK.

  2. Click Data, and then choose Add a New Data Source. Use the same process that you did earlier in the chapter to add the Sales database as an entity data model to the Visual Studio solution.

  3. After you add the Sales database, right-click the project, select Add, and then click Class. Call the class SalesObject, and then add the following bolded code to the new class.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace AddSalesRecordWebPart
    {
    
      class SalesObject
      {
        public int companyID { get; set; }public string companyName { get; set; }public int? fy08Sales { get; set; }public int? fy09Sales { get; set; }public int? fy10Sales { get; set; }
      }
    }
    
  4. Open the Service1.svc file and amend the file, using the following bolded code.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Runtime.Serialization;
    using System.ServiceModel;
    using System.ServiceModel.Web;
    using System.Text;
    namespace GetSPSalesData
    {
      public class Service1 : IService1
      {
        SalesEntities mySalesData = new SalesEntities();List<SalesObject> mySalesList = new List<SalesObject>();public List<SalesObject> getAllSalesData(){var returnSalesData = (from sales in mySalesData.Sales_Dataselect sales).ToArray();foreach (var s in returnSalesData){SalesObject tempSales = new SalesObject();tempSales.companyID = s.CompanyID;tempSales.companyName = s.CompanyName.ToString();tempSales.fy08Sales = s.FY08Sales;tempSales.fy09Sales = s.FY09Sales;tempSales.fy10Sales = s.FY10Sales;mySalesList.Add(tempSales);};return mySalesList;}public void addSalesRecord(int paramCompanyID, string paramCompanyName,int paramFY08Sales, int paramFY09Sales, int paramFY10Sales){SalesObject newRecord = new SalesObject(){companyID = paramCompanyID,companyName = paramCompanyName,fy08Sales = paramFY08Sales,fy09Sales = paramFY09Sales,fy10Sales = paramFY10Sales,};Sales_Data myNewSalesRecord = new Sales_Data();using (SalesEntities dataContext = new SalesEntities()){myNewSalesRecord.CompanyID = newRecord.companyID;myNewSalesRecord.CompanyName = newRecord.companyName;myNewSalesRecord.FY08Sales = newRecord.fy08Sales;myNewSalesRecord.FY09Sales = newRecord.fy09Sales;myNewSalesRecord.FY10Sales = newRecord.fy10Sales;dataContext.AddToSales_Data(myNewSalesRecord);dataContext.SaveChanges();}}
      }
    }
    
  5. Open the IService1.cs file and ensure that the following bolded code replaces the default code. (This is your service contract that must map to the two methods that you have in your service code.)

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Runtime.Serialization;
    using System.ServiceModel;
    using System.ServiceModel.Web;
    using System.Text;
    
    namespace GetSPSalesData
    {
      [ServiceContract]
      public interface IService1
      {
        [OperationContract]List<SalesObject> getAllSalesData();[OperationContract]void addSalesRecord(int paramCompanyID,string paramCompanyName,int paramFY08Sales,int paramFY09Sales,int paramFY10Sales);
      }
    }
    
  6. You have now completed the custom WCF service. Press F5 to build and test the service.

  7. After the test page invokes, you can deploy the service to IIS the same way that you published and deployed the ASP.NET service to IIS. To do this, create a new folder on your local server drive (for example, C:\Wrox\MyWCFService), publish the solution to that folder, create a new Web site in IIS, and then point the virtual directory to that newly published folder and code.

  8. Before you can use the WCF service in SharePoint, however, there is another configuration step that is required. If you open the WCF service project, you'll see a web.config file, which contains all of your WCF service configurations. WCF provides more granular and flexible control over your Web service settings, and you can use the web.config file to configure many service settings. To enable the service in SharePoint, you must copy and paste the Service Model settings in your web.config file into your SharePoint site's web.config file. This way, when SharePoint uses the endpoint URL, it understands the bindings and other properties defined in the config file it needs to use to properly handle the WCF service.

    To find the specific elements that you need to copy, double-click the web.config file in the Visual Studio project, and then copy all of the code between the system.serviceModel tags from the web.config file in the Visual Studio project and add it to the appropriate places in the SharePoint web.config file. You can typically find the SharePoint web.config file in the following directory.

    c:\inetpub\wwwroot\wss\VirtualDirectories\<SharePoint_Server>\

    The following code snippet shows the copied system.serviceModel elements in the SharePoint web.config file.

    …
    <system.serviceModel>
      <serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
      <bindings>
        <basicHttpBinding>
          <binding name="projectBasicHttpConf" closeTimeout="00:01:00"
              openTimeout="00:01:00" receiveTimeout="00:10:00"
              sendTimeout="00:01:00" allowCookies="true"
              maxBufferSize="4194304" maxReceivedMessageSize="500000000"
              messageEncoding="Text" transferMode="StreamedResponse">
            <security mode="TransportCredentialOnly">
              <transport clientCredentialType="Windows"
                proxyCredentialType="Windows" realm="" />
            </security>
          </binding>
        </basicHttpBinding>
    
        <wsHttpBinding>
          <binding name="WSHttpBinding_IService1" closeTimeout="00:01:00"
            openTimeout="00:01:00" receiveTimeout="00:10:00"
              sendTimeout="00:01:00"
            bypassProxyOnLocal="false" transactionFlow="false"
              hostNameComparisonMode="StrongWildcard"
            maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
            messageEncoding="Text" textEncoding="utf-8"
              useDefaultWebProxy="true"
            allowCookies="false">
            <readerQuotas maxDepth="32" maxStringContentLength="8192"
              maxArrayLength="16384"
              maxBytesPerRead="4096" maxNameTableCharCount="16384" />
            <reliableSession ordered="true" inactivityTimeout="00:10:00"
              enabled="false" />
            <security mode="Message">
              <transport clientCredentialType="Windows"
                proxyCredentialType="None"
                realm="" />
              <message clientCredentialType="Windows"
                negotiateServiceCredential="true"
                algorithmSuite="Default" />
            </security>
          </binding>
        </wsHttpBinding>
      </bindings>
        <client>
          <endpoint address="http://demo2010a.contoso.com:1122/Service1.svc"
            binding="wsHttpBinding" bindingConfiguration=
              "WSHttpBinding_IService1"
            contract="SalesWCFService.IService1" name="WSHttpBinding_IService1">
            <identity>
              <dns value="localhost" />
            </identity>
          </endpoint>
        </client>
    </system.serviceModel>
    …
    
  9. With the service deployed and SharePoint's web.config file now configured, you are ready to use the service in a SharePoint application. To test the service from IIS, right-click the service in Content view, and then select Browse. When the service page loads, navigate to Service1.svc and copy the URL from the Internet browser.

  10. Open Visual Studio, create a new Empty SharePoint project, provide a name for it (for example, AddSalesDataRecordWebPart) and then click OK. Right-click the project, click Add, select New Item, and then add a Web Part project to it. Provide a name for the Web part (for example, SalesRecordWebPart) and then click Add.

  11. Add a reference to the URL by right-clicking the References node and clicking Add Service Reference. Copy the IIS URL into the URL field, and then click Go. When the endpoint is loaded into the Service Reference dialog box, provide a name for the service and then click Add.

  12. Right-click the main Web part class file and then click View Code. Add the following bolded code to the main Web part class file.

    using System;
    using System.ComponentModel;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Web.UI.WebControls.WebParts;
    using Microsoft.SharePoint;
    using Microsoft.SharePoint.WebControls;
    using System.Text;
    namespace AddSalesRecordWebPart.SalesRecordWebPart
    {
      [ToolboxItemAttribute(false)]
      public class SalesRecordWebPart : WebPart
      {
    
        DataGrid datagrdSalesView = new DataGrid();TextBox txtbxCompanyID = new TextBox();TextBox txtbxCompanyName = new TextBox();TextBox txtbxFY08Sales = new TextBox();TextBox txtbxFY09Sales = new TextBox();TextBox txtbxFY10Sales = new TextBox();Button btnLoad = new Button();Button btnGet = new Button();protected override void Render(HtmlTextWriter writer){txtbxCompanyID.Enabled = true;txtbxCompanyName.Enabled = true;txtbxFY08Sales.Enabled = true;txtbxFY09Sales.Enabled = true;txtbxFY10Sales.Enabled = true;btnLoad.Text = "Add";btnGet.Text = "Get";writer.Write("<table><tr>");writer.Write("<td><b>Sales Information</b></td><td></td></tr>");writer.Write("<tr><td>Sales Data:</td><td>");datagrdSalesView.RenderControl(writer);writer.Write("</td></tr><tr><td>Company ID:</td><td>");txtbxCompanyID.RenderControl(writer);writer.Write("</td></tr><tr><td>Company Name:</td><td>");txtbxCompanyName.RenderControl(writer);writer.Write("</td></tr><tr><td>FY 08 Sales:</td><td>");txtbxFY08Sales.RenderControl(writer);writer.Write("</td></tr><tr><td>FY 09 Sales:</td><td>");txtbxFY09Sales.RenderControl(writer);writer.Write("</td></tr><tr><td>FY 10 Sales:</td><td>");txtbxFY10Sales.RenderControl(writer);writer.Write("</td></tr><tr><td>");btnGet.RenderControl(writer);writer.Write("</td><td>");btnLoad.RenderControl(writer);writer.Write("</td></tr></table>");btnLoad.Click += new EventHandler(btnLoad_Click);btnGet.Click += new EventHandler(btnGet_Click);}void btnGet_Click(object sender, EventArgs e){SalesWCFService.Service1Client proxy =new SalesWCFService.Service1Client();var salesData = proxy.getAllSalesData();List<SalesObject> mySalesInfoList = new List<SalesObject>();foreach (var item in salesData){SalesObject tempEntity = new SalesObject();tempEntity.companyID = item.companyID;tempEntity.companyName = item.companyName.ToString();tempEntity.fy08Sales = item.fy08Sales;tempEntity.fy09Sales = item.fy09Sales;tempEntity.fy10Sales = item.fy10Sales;mySalesInfoList.Add(tempEntity);}datagrdSalesView.DataSource = mySalesInfoList;datagrdSalesView.DataBind();}void btnLoad_Click(object sender, EventArgs e){int companyID = Int32.Parse(txtbxCompanyID.Text);string companyName = txtbxCompanyName.Text;int fy08Sales = Int32.Parse(txtbxFY08Sales.Text);int fy09Sales = Int32.Parse(txtbxFY09Sales.Text);int fy10Sales = Int32.Parse(txtbxFY10Sales.Text);SalesWCFService.Service1Client proxy =new SalesWCFService.Service1Client();proxy.addSalesRecord(companyID, companyName, fy08Sales,fy09Sales, fy10Sales);}
      }
    }
    
  13. After you finish, click Build, and then Deploy to deploy the Web part to SharePoint.

  14. After the Web part successfully builds, navigate to SharePoint and use an existing page or create a new Web part page, and then click Add a new Web part.

  15. Select the Custom category, and add the new Web part you just created. Click Get to invoke the one Web method within your custom WCF service. Then, add some data and click Add to add some data to the SQL database via your WCF service. The result should look similar to Figure 8.

    Figure 8. Sales Web part

    Sales Web part

How it works

In much the same way that you created an ASP.NET Web service and then consumed it in an application, you walked through a similar process here using a custom WCF service. However, there were some differences this time, even though you used the same database in your service code.

First, your service code included the capability to add a record this time, as opposed to just retrieving data (addSalesRecord). In this method, you passed a number of parameters that you would eventually insert as a record. To do this, you created a new object, and then, using the database data context, you added an instance of the object to the database and saved the changes by calling the SaveChanges method.

public void addSalesRecord(int paramCompanyID, string paramCompanyName,int paramFY08Sales, int paramFY09Sales, int paramFY10Sales){SalesObject newRecord = new SalesObject(){companyID = paramCompanyID,companyName = paramCompanyName,fy08Sales = paramFY08Sales,fy09Sales = paramFY09Sales,fy10Sales = paramFY10Sales,};Sales_Data myNewSalesRecord = new Sales_Data();using (SalesEntities dataContext = new SalesEntities()){myNewSalesRecord.CompanyID = newRecord.companyID;myNewSalesRecord.CompanyName = newRecord.companyName;myNewSalesRecord.FY08Sales = newRecord.fy08Sales;myNewSalesRecord.FY09Sales = newRecord.fy09Sales;myNewSalesRecord.FY10Sales = newRecord.fy10Sales;dataContext.AddToSales_Data(myNewSalesRecord);dataContext.SaveChanges();}}

Second, you added some configuration information to the SharePoint web.config file after deploying the WCF service. While this does make for an extra step in the development and deployment process, it does provide more granular control over the security and bindings for your services — and is very much typical of a WCF service. However, remember that what you need is typically created in your web.config file (unless you want to further customize the configuration settings).

Lastly, instead of using BCS (and the BDC Metadata model), you used the Visual Web part as your client application. In this case, implementing the service was fairly straightforward and only required that you call the addSalesRecord method and pass in a number of variables — which the user entered into the textboxes.

void btnLoad_Click(object sender, EventArgs e){int companyID = Int32.Parse(txtbxCompanyID.Text);string companyName = txtbxCompanyName.Text;int fy08Sales = Int32.Parse(txtbxFY08Sales.Text);int fy09Sales = Int32.Parse(txtbxFY09Sales.Text);int fy10Sales = Int32.Parse(txtbxFY10Sales.Text);SalesWCFService.Service1Client proxy =new SalesWCFService.Service1Client();proxy.addSalesRecord(companyID, companyName, fy08Sales,fy09Sales, fy10Sales);}

The example in this exercise deployed the WCF service to IIS, so when you created your client application, it was calling the service from IIS. However, in SharePoint 2010, you can equally deploy a WCF service to the SharePoint root (that is, the ISAPI folder). The way in which you would deploy to the SharePoint root would be as follows:

  1. Create an Empty SharePoint Project and set it to Deploy as farm solution.

  2. Add a WCF Service Library to the solution.

  3. Copy the IService.cs and Service.cs files to the SharePoint project.

  4. Add your service operations and contracts to the two service files.

  5. Create a mapped SharePoint folder to the ISAPI folder.

  6. Add a .svc file to the ISAPI mapped folder, and add the service registration information.

  7. Deploy the SharePoint project to your SharePoint site.

Once you deploy the WCF service to SharePoint, you can consume the service either server-side or client-side through Windows Form, WPF, or even Silverlight applications.

Note

While there is no walkthrough presented in this discussion for a WCF solution deployed to the SharePoint root, there is a code accompaniment (WCFServiceApp.zip) that is available for you to download. You can review the project to see how it is structured, as well as the way in which a client application calls the WCF service.

You can build many more interesting and complex applications using WCF, so you should explore it more as you sharpen your SharePoint development skills.

RESTful Web Services

You can also use the Representational State Transfer (REST) services in SharePoint 2010. Although REST is less of a service and more of a communications protocol, SharePoint 2010 supports REST to give you better data access and programmability.

In some cases, the REST capabilities are surfaced using WCF services. For example, in Chapter 5, you leveraged the WCF Data services and REST capabilities by using the Listdata service (listdata.svc).

What this functionality provides to the developer is a way to interact with SharePoint data in a strongly typed way. However, the strongly typed interaction with SharePoint data is not the only benefit provided by the REST APIs. They also provide a way to interact with other types of data in SharePoint, such as Excel data. You accomplish this through the REST protocols, which are Atom, AtomPub, and RSS.

In this section, you'll see more of the REST protocols at work (as opposed to the WCF Data services, which you already saw in Chapter 5) to interact with Excel data in SharePoint.

The REST protocols enable you to access data in Excel documents in various read/write ways. For the following example, create an Excel 2010 spreadsheet, add some data to a workbook (as shown in Figure 9), and create a named range called Sales. Next, create a chart from the named range by selecting all of the data in the table, clicking Insert, then Chart, and then selecting the Bar Chart to add the chart into the workbook. Note that the chart is called Chart 1 by default.

Figure 9. Creating a Sales spreadsheet

Creating a Sales spreadsheet

 

After you create the workbook, save and upload the spreadsheet into SharePoint — for example, into the Shared Documents document library with the name RestExample.xlsx. With the Excel document in SharePoint, you can now use REST to retrieve or insert data.

Let's walk through an example where you retrieve the data by using the REST protocols.

Try It Out: Using REST to interact with data in Excel

REST is a lightweight set of protocols that you can use to interact with data in various ways, one of which is retrieving data from Excel.

To retrieve data from an Excel spreadsheet by using REST

  1. Open your Internet browser and navigate to your SharePoint instance to ensure that you have connectivity to your server.

  2. Type the following URI into your Internet browser.

    http://<server name>/_vti_bin/ExcelRest.aspx/Shared%20Documents/RestExample.xlsx/Model

  3. In your Internet browser, you should now see something similar to Figure 10. What you're seeing is an ATOM feed of the types of items in your workbook that are accessible using the REST protocols.

    Figure 10. Atom feed of available item types

    Atom feed of available item types

  4. Because you created a named range in the spreadsheet, you can access the named range using theAtom feed. To do so, type the following URI into the Internet browser.

    http://intranet.contoso.com/\_vti\_bin/ExcelRest.aspx/Shared%20Documents/RestExample.xlsx/Model/Ranges('Sales')?$format=html

  5. You should now see something similar to Figure 11, which shows the result of the Atom feed — the table that you made the named range in your Excel spreadsheet.

    Figure 11. Surfacing a named range in the browser

    Surfacing a named range in the browser

  6. Lastly, type the following URI into your Internet browser to expose the chart that you also created in the spreadsheet.

    http://intranet.contoso.com/\_vti\_bin/ExcelRest.aspx/Shared%20Documents/RestExample.xlsx/Model/Charts('Chart%201')

How it works

REST is a lightweight way to interact with SharePoint 2010. By using the URIs, you can interact with data in an Excel spreadsheet within your SharePoint site. You must leverage the URIs, though, with an Excel document that is stored in the SharePoint site, because you are either using the ExcelRest.aspx redirect or Listdata.svc (for strongly typed data programmability) to interact with that data.

There are also a number of supported REST return formats. For example, supported return formats include HTML, Atom, image, or workbook. To enable this return data, you append the REST URI with ?$format=html to return, for example, the named range as HTML. This is what you did with the Sales named range in the walkthrough. Note that you could also return the data as an Atom feed as is indicated by the ?$format=atom that is appended to the end of the following URI.

http://intranet.contoso.com/\_vti\_bin/ExcelRest.aspx/Shared%20Documents/RestExample.xlsx/Model/Ranges('Sales')?$format=atom

You saw one way to leverage the Listdata service in Chapter 5 (where you developed a client application to talk to SharePoint lists), and here you should be thinking how you can develop applications that leverage the lightweight REST protocol to get and put data into SharePoint lists, or access data in Excel spreadsheets programmatically.

Azure and SharePoint

A growing trend in software development is cloud computing. Cloud computing is where code and data live in the cloud so that organizations can both consume and deploy services in an Internetbased data center for hosting. The business mechanics of cloud computing can make a lot of sense when thinking about things like hardware, upgrading, administration, and software maintenance. Cloud computing offsets these costs by moving the management and maintenance of applications to companies like Microsoft.

One of the key Microsoft cloud offerings is the Windows Azure platform, which is a set of cloud capabilities that provides specific services to both those trying to host services in the cloud and those trying to develop and deploy services in the cloud. Interestingly, the Azure platform is not limited to being consumed by cloud-only applications. You can integrate Azure services with on-premises applications as well. In fact, the easy way to think about an Azure service is that it is very similar to any other service endpoint — except that it is deployed and hosted in the cloud.

The demand for cloud computing is big, and, in the near term, you'll see many companies trying to integrate more with the Windows Azure platform. The question, then, is how does SharePoint integrate with the cloud?

At present, SharePoint can integrate with Windows Azure services; again, it is just another endpoint. Thus, you build and deploy a service in the cloud and, as long as you have connectivity to the service, you can integrate and run it with SharePoint. While this book mainly focuses on SharePoint on-premises (that is, SharePoint Server 2010), there is no reason why you cannot integrate Azurebased services with SharePoint does make for an extra step in the development and deployment process, Online (for example, using sandboxed solutions as your point of integration) when it is released later in 2010.

Integrating SharePoint with Azure services or data primarily means two things at present. The first is that you can integrate with services that are already hosted on Azure. Or, you can build your own Azure services (or applications), deploy these services in the cloud, and then integrate these services with SharePoint. The Windows Azure platform provides a set of developer tools and a replicated developer environment where you can test any services you will deploy to the cloud.

Note

For more information on how to get started using Windows Azure, see the Windows Azure Platform home page.

An interesting data service that is built on Azure is a technology codenamed 'Dallas,' where companies are hosting large quantities of public data on Azure, and then, through a subscription model, you can build applications that leverage that data in some capacity. While the technology is currently limited, in the future it is sure to grow in use and popularity, because the data will grow to include census, crime, and news data — and other types of data that can prove interesting when mined and analyzed in different ways.

In this section, you'll see how you can integrate Dallas data hosted on Azure integrated with SharePoint. To complete the exercise that follows, you'll need to have a Live ID and a developer key to access the Dallas data and services.

To get a developer key, navigate to Codename Dallas and then sign in with your Live ID. Click Home and follow the instructions to get your developer key sent to you via email. It's a very simple process and will only take you a couple of minutes. After you have your developer key, click Catalog, and then subscribe to one or more of the data catalogs. When you subscribe to a catalog, it is then added to your Subscriptions. For this walkthrough, use the infogroup data catalog that is hosted on Azure.

Try It Out: Creating a Web Part integrated with Azure

Tip

Code file (AzureProject.zip) available for download at Wrox.com.

Azure is a very powerful cloud-based platform that hosts services and data.

To integrate Azure with SharePoint

  1. Navigate to your Dallas Azure Catalog page and click the link, Click here to explore the dataset as shown in Figure 12.

    Figure 12. Infogroup data catalog

    Infogroup data catalog

  2. Explore the catalog using the Web-based filters to get a better sense for what public data is returned from your filtering.

  3. Copy the Account Key, Unique User ID, and link feed to the catalog (for example, https://api.sqlazureservices.com/InfoUsaService.svc/businessAnalytics/canada?$format=atom10) to a text document and save them to your desktop.

  4. Open Visual Studio 2010 and create an Empty SharePoint project and provide a name for the project (for example, AzureProject). Add the Web part item-level template to the Empty SharePoint project.

  5. Right-click the project, click Add, and then choose Class. Call the class Customer and add the following bolded code to the class.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace AzureProject
    {
    
      class Customer
      {
    
        public string contactName { get; set; }public string companyName { get; set; }public string companyAddress { get; set; }public string companyCity { get; set; }public string companyProvince { get; set; }public string companyPostalCode { get; set; }public string companyPhone { get; set; } 
      }
    
    }
    

    Amend the .webpart file so that it has a more intuitive title and description.

    …
      <properties>
        <property name="Title" type="string">Azure Dallas Web Part</property>
        <property name="Description" type="string">Web Part that displays
          Dallas data from Azure.</property>
      </properties>
    …
    
  6. In the main Web part class, add the following bolded code. Where noted in the code, add your account key, unique user ID, and the link to the data catalog.

    using System;
    using System.ComponentModel;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Web.UI.WebControls.WebParts;
    using Microsoft.SharePoint;
    using Microsoft.SharePoint.WebControls;
    using Microsoft.Dallas.Services;
    using System.Net;
    using System.IO;
    using System.Xml.Linq;
    using System.Collections.Generic;
    using System.Linq;
    namespace AzureProject.AzureWebPart
    
    {
      [ToolboxItemAttribute(false)]
      public class AzureWebPart : WebPart
      {
        Button btnGetAzureData = new Button();DataGrid datagrdAzureData = new DataGrid();Label lblData = new Label();string myAccountKey = "<your account key>"string myUniqueUserId = "<your user ID>";string myDallasURL = "<your Dallas URL>";
    
        protected override void CreateChildControls()
    
        {btnGetAzureData.Text = "Load Azure Data";lblData.Text = "Azure Data: ";this.Controls.Add(new LiteralControl("<table><tr><td>"));this.Controls.Add(lblData);this.Controls.Add(new LiteralControl("</td><td>"));this.Controls.Add(datagrdAzureData);this.Controls.Add(new LiteralControl("</td><tr><td></td<td>"));this.Controls.Add(btnGetAzureData);this.Controls.Add(new LiteralControl("</td></tr></table>"));btnGetAzureData.Click += new EventHandler(btnGetAzureData_Click);}void btnGetAzureData_Click(object sender, EventArgs e){List<Customer> customerSalesLeads = new List<Customer>();WebRequest azureWebRequest = WebRequest.Create(myDallasURL);azureWebRequest.Headers.Add("$accountKey", myAccountKey);azureWebRequest.Headers.Add("$uniqueUserID", myUniqueUserId);HttpWebResponse azureWebResponse = (HttpWebResponse)azureWebRequest.GetResponse();Stream AzureDataStream = azureWebResponse.GetResponseStream();StreamReader reader = new StreamReader(AzureDataStream);string responseFromAzure = reader.ReadToEnd();XDocument xmlAzureResultData = XDocument.Parse(responseFromAzure);XNamespace nsContent = "http://www.w3.org/2005/Atom";XNamespace nsProperties = "https://schemas.microsoft.com/ado/2007/08/dataservices/metadata";XNamespace nsValue = "https://schemas.microsoft.com/ado/2007/08/dataservices";var result = (from q in xmlAzureResultData.Descendants(nsContent +"entry")where q.Element(nsContent + "content").Element(nsProperties + "properties").Element(nsValue + "City").Value == "SOOKE"select new Customer{contactName = q.Element(nsContent +"content").Element(nsProperties +"properties").Element(nsValue +"ContactName").Value.ToString(),companyCity = q.Element(nsContent +"content").Element(nsProperties +"properties").Element(nsValue +"CompanyName").Value.ToString(),companyAddress = q.Element(nsContent +"content").Element(nsProperties +"properties").Element(nsValue +"Address").Value.ToString(),companyName = q.Element(nsContent +"content").Element(nsProperties +"properties").Element(nsValue +"City").Value.ToString(),companyProvince = q.Element(nsContent +"content").Element(nsProperties +"properties").Element(nsValue +"Province").Value.ToString(),companyPostalCode = q.Element(nsContent +"content").Element(nsProperties +"properties").Element(nsValue +"PostalCode").Value.ToString(),companyPhone = q.Element(nsContent +"content").Element(nsProperties +"properties").Element(nsValue +"Phone").Value.ToString()});foreach (var c in result){Customer tempCustomer = new Customer();tempCustomer.contactName = c.contactName;tempCustomer.companyCity = c.companyCity;tempCustomer.companyAddress = c.companyAddress;tempCustomer.companyName = c.companyName;tempCustomer.companyProvince = c.companyProvince;tempCustomer.companyPostalCode = c.companyPostalCode;tempCustomer.companyPhone = c.companyPhone;customerSalesLeads.Add(tempCustomer);}datagrdAzureData.DataSource = customerSalesLeads;datagrdAzureData.DataBind();reader.Close();AzureDataStream.Close();azureWebResponse.Close();}
      }
    }
    
  7. After you add the code, click Build to build the project. After the project has successfully built, click Build and then choose Deploy Solution to deploy the Web part to SharePoint.

  8. Once the Web part has deployed, navigate to your SharePoint site and either create a new Web part page or use an existing one. Click Add a web part, and then navigate to the Custom category. Add your newly created Azure Web part.

  9. Click Load Azure Data to invoke the Web request to the Azure service and load the Dallas data. The results should look similar to Figure 13.

    Figure 13. Rendered Azure data in Web part

    Rendered Azure data in Web part

 

How it works

This example opens up the opportunity for you to begin to code against Azure-based services that live in the cloud. However, you shouldn't think of these services as any different from other types of services. These are simply a different endpoint.

In this walkthrough, rather than using the service proxies as you did in the ASP.NET and WCF examples, you used the WebRequest object to interact with the Azure data. The WebRequest object is a .NET class that represents a request/response model for working with data that lives in the cloud. Using this class, the request was sent from the client application using a specific URI (in this case, the Dallas data URL), and the response was handled by reading the response stream into an XDocument object.

Note

For more information on the WebRequest class, see the WebRequest Class on the MSDN Library.

In the walkthrough, the bulk of the code was invoked when you clicked the button in the Web part (btnGetAzureData). This invoked the Click event, which then created a new WebRequest object, made the request to the specific Dallas URL (myDallasURL), and then added your account key and unique user ID as values within the request.

…
      WebRequest azureWebRequest = WebRequest.Create(myDallasURL);azureWebRequest.Headers.Add("$accountKey", myAccountKey);azureWebRequest.Headers.Add("$uniqueUserID", myUniqueUserId);HttpWebResponse azureWebResponse = (HttpWebResponse)azureWebRequest.GetResponse();Stream AzureDataStream = azureWebResponse.GetResponseStream();StreamReader reader = new StreamReader(AzureDataStream);string responseFromAzure = reader.ReadToEnd();XDocument xmlAzureResultData = XDocument.Parse(responseFromAzure);XNamespace nsContent = "http://www.w3.org/2005/Atom";XNamespace nsProperties = "https://schemas.microsoft.com/ado/2007/08/dataservices/metadata";XNamespace nsValue = "https://schemas.microsoft.com/ado/2007/08/dataservices";
…
      datagrdAzureData.DataSource = customerSalesLeads;datagrdAzureData.DataBind();reader.Close();AzureDataStream.Close();azureWebResponse.Close();

…

After making the request, a good portion of the code within the Click event constructed a query that could be used to get the specific information you wanted. (You can certainly optimize this code with LINQ to get a more concise query against the returned data set, and you would likely want to emit the HTML formatting using the HtmlTextWriter class, as you've seen throughout the book.) In this case, you created a query that parsed all records from the response stream that were located in the city of Sooke, British Columbia. After you bound the returned data to the datagrid (datagrdAzureData), you then disposed all of the objects associated with the WebRequest.

Summary

Service-based applications open up a vast amount of potential for building interesting applications that span heterogeneous systems. In this chapter, you saw the increased support for services of all kinds in SharePoint 2010. Specifically, you learned about native and custom ASP.NET Web services, custom WCF services, the REST protocols, and Azure services. All of these provide you with different capabilities and levels of functionality that can extend out into the enterprise, or out into the wider cloud.

As a beginning developer, your first option should always be to see if the service exists already before creating a custom service. SharePoint 2010 has a rich set of native Web services, and you'll find that these will often fit the bill. However, if the functionality does not exist in the native SharePoint Web services, then custom services may be the option. WCF services are being used more these days, as they offer more flexibility and power over security. However, that's not to say that you could not use custom ASP.NET services as well. Many organizations still leverage ASP.NET for their custom services.

With either ASP.NET or WCF, you also have the option to deploy to IIS, or to deploy to the SharePoint root. Deploying to IIS provides you with a higher level of scalability, but leveraging the SharePoint root deploys your services as a "trusted" context with SharePoint. The flip side is that any services deployed to the ISAPI folder can get deleted through routine maintenance and upgrades.

If you're looking for more lightweight services, then REST would be the option to use to interact with SharePoint data. As you've seen, combined with WCF Data services, you can do some strongly typed programming against SharePoint lists. And, in this chapter, you have seen how you can very easily use the REST protocols when interacting with Excel documents.

When it comes to the cloud, Microsoft's newest offering is Azure. It will be exciting to see where Azure moves in the future. Cloud computing is a reality, and many companies are moving in this direction.

In Chapter 11, you'll see how you can integrate in different ways with Office 2010.

Exercises

  1. Explore the native ASP.NET Web services in SharePoint 2010 and build some applications using other native Web services.

  2. Create either an ASP.NET or WCF Web service, and then deploy it in the SharePoint 2010 root, as opposed to deploying it to IIS.

  3. Use the REST URI that points to your Sales named range and surface this within a Word document.

  4. Create a custom Azure service and then build a SharePoint Web part that implements that service.

What you learned in this chapter

Items

Description

ASP.NET Services

ASP.NET 2.0 services provide SOAP and WSDL-based services to interact with SharePoint. SharePoint 2010 provides an array of native ASP.NET services that you can leverage, as well as the capability to support custom services.

WCF Services

First supported in .NET 3.0, WCF provides more advanced and flexible management over Web service implementation. This follows similar standards to ASP.NET but expands to support broader settings such as security and bindings.

REST

REST is a set of protocols that are not only supported through WCF services in SharePoint (for example, Listdata.svc) but also through lightweight URIs. REST enables you to leverage the power of WCF Data services or issue URI commands to the browser to retrieve Excel data.

Azure

Windows Azure is the platform in the cloud that provides you with the capability to build, deploy, and host services and data on the Internet using a scalable infrastructure.

For more information, see the following resources:

About the Author

Steve Fox is a senior technical evangelist in the Developer Platform Evangelism group at Microsoft. He has worked in the IT industry for more than 15 years, and has worked in natural language, search, developer tools, and, more recently, Office Business Application and SharePoint development. Mr. Fox also presents at both domestic and international conferences (TechEd, PDC, DevConnections, and SAP TechEd, among others), and has written several books, including Professional SharePoint 2007 Development using Silverlight 2 (Indianapolis: Wiley, 2009) and Microsoft .NET and SAP (Redmond, WA: Microsoft Press, 2009), and articles for MSDN Magazine and other technical magazines. Mr. Fox lives in Redmond, Washington.