Building a SharePoint Service Application to provide auto-completion services for AJAX-enabled rich user controls Contents Introduction .................................................................................................................................................. 2 Author’s Notes .............................................................................................................................................. 3 What You’ll Need .......................................................................................................................................... 4 Required .................................................................................................................................................... 4 Optional .................................................................................................................................................... 4 Part One - The Service Application ............................................................................................................... 4 Anatomy of a SharePoint Service Application .......................................................................................... 4 SPService ............................................................................................................................................... 4 SPServiceInstance ................................................................................................................................. 4 SPServiceApplication............................................................................................................................. 5 SPServiceProxy ...................................................................................................................................... 5 SPServiceApplicationProxy.................................................................................................................... 5 Implementing the Service Application .................................................................................................. 6 Part Two – the Service Application’s Admin Interface ............................................................................... 14 The Create and Manage Application Pages ........................................................................................ 14 Part Three – The WCF Service Endpoint ..................................................................................................... 23 Part Four – The User Application Page ....................................................................................................... 24 Download the ASP.NET AJAX Control Toolkit ......................................................................................... 24 Add a New Project and Test Page ........................................................................................................... 25 Bringing It All Together ............................................................................................................................... 28 Introduction With each new release of SharePoint, Microsoft has managed to further improve this platform’s programmability, extensibility and manageability. Among many other exciting new features and capabilities, the new 2010 release of SharePoint now provides developers with ASP.NET AJAX as a firstclass tool in our proverbial toolbox. AJAX has been around for some time now, and it is great to finally see both native and custom SharePoint applications will be enabled with the same rich, interactive user controls we’ve come to expect from quality browser-based applications. Yet another exciting technology that ships with SharePoint 2010 is the Service Application Framework. The Service Application Framework allows developers to create robust and scalable shared services which can be consumed by multiple SharePoint web applications. In this article, I’ll show you how to create and provision a SharePoint Service Application. Within the service application I’ll define a WCF service endpoint which provides auto-completion services to ASP.NET AJAX-enabled controls. Finally I’ll leverage this WCF service and the ASP.NET AJAX Toolkit to provide users with a simple Geo-locator page. The Geo-locator will prompt a user for a city and state, suggesting known values in real-time as the form’s fields are completed. Once a city and state have been keyed, the user will be shown the specified location on a satellite map. Author’s Notes Admittedly, the use case set forth in this demonstration in somewhat contrived. Using SharePoint’s Service Application Framework to simply provide AJAX controls with auto-completion services is really beating a small nail with a big hammer. In most real-world production scenarios, such trivial functionality could probably be achieved with a simpler site-level web service. I’ve chosen such a simple use case so as to not distract from the primary purpose of the article, which is to illustrate how to create and provision the skeleton of a simple SharePoint Service Application. The topic of SharePoint Service Applications is broad and technically advanced. Areas such as scalability, fault-tolerance, external service publishing, security, database provisioning and data backup are left for another demonstration. That being said, in this article I will get you started by showing the basics of creating, provisioning and hooking into the Central Administration management interface for SharePoint Service Applications. This demonstration is accompanied by a complete Visual Studio solution. All code artifacts covered in this narrative are included in the solution. I will walk you through the process of creating the solution from scratch. As I add each artifact, I will highlight its salient points, but I will assume you also have the Visual Studio solution open to view complete code listings. There are a few utility and helper classes in the project which I don’t cover in this narrative, as I believe these artifacts are self-evident. The Visual Studio solution is meant to be a starting point for you to create your own SharePoint Service Applications. I hope you will be able to take the work done here and refactor it to a launching point for your own real-world use cases. What You’ll Need To follow along with this demonstration, I assume you have the following requirements installed and functioning properly. Required SharePoint 2010 – WSS only will do. Visual Studio 2010 Visual Studio 2010 SharePoint Tools Optional WSS 2010 SDK .NET Reflector Fiddler I also assume that you are an intermediate to advanced SharePoint developer familiar with the SharePoint object model and the latest ASP.NET, Visual Studio and SharePoint development tools. Part One - The Service Application In SharePoint 2010, the Service Application Framework provides you with the ability to create hosted, middle-tier services. These shared services can then provide data or processing resources to other SharePoint features. Native SharePoint applications such as search and Excel Services are built by using this platform. The platform is now available in SharePoint 2010 for third parties to also build upon. Among other things, the Service Application Framework provides: Built-in support for building applications using the Windows Communications Framework (WCF). Integration with the standard SharePoint management experience, including Administration and configuration using SharePoint Central Administration. Anatomy of a SharePoint Service Application SPService A service provides a very narrow range of functionality that usually does not include end-to-end functions that are valuable in themselves. Services typically run invisibly and have little or no UI. Every SPService object has an Instances property that holds all the instances of the service that are running on various servers in the farm. No more than one instance of each service runs on any one server, but some services have multiple instances, each one running on a different server. Each instance is represented by an object of a class derived from SPServiceInstance. SPServiceInstance SPServiceInstance represents an instance of a service on a server in the farm. A service instance is independent from, and identical in functionality, to all other server instances of the same type. As long as one service instance of a given service remains online, the service is fully functional. Service instances may be in the ‘started’ or ‘stopped’ state. A service instance provides the host process for service applications. SPServiceApplication A service application is hosted by a service instance. Service applications are generally created by administrators. They provide the service interface, containing the administrator settings. Service applications may own user data. SPServiceProxy A SPServiceProxy is simply the parent of the SPServiceApplicationProxy. It is the equivalent of a SPService on the server side, which is the parent of a SPServiceApplication. You can also think of these parent objects as class factories for the child objects, if that makes more sense to you. SPServiceApplicationProxy Service application proxies provide the public (front-end) interface to a service application. They allow client code to consume remote service applications. Service applications may not be installed locally and therefore cannot be called directly. Implementing the Service Application 1. In Visual Studio 2010 I start out by creating a new Empty SharePoint project. 2. When prompted by the SharePoint Customization Wizard, I’m going to target the Central Administration web, as this is where the service application will be deployed. Also in the wizard, I’ll select the option to Deploy as a full-trust solution. 3. Next, I add a new class to then project and name it AutoCompletionService.cs. As with all code artifacts in this demonstration, I’ll cover the highlights of this class, but refer to the accompanying Visual Studio 2010 sample project for the complete listing. The AutoCompletionService class inherits the SPIisWebService class and implements the IServiceAdministration interface. Because this class is a persisted object, it must also be decorated with the System.Runtime.InteropServices.Guid attribute and assigned a unique guid. 4. For serialization purposes, the AutoCompletionService class must have a default, parameter-less constructor. This class also implements a singleton pattern to provide the means for acquiring an instance of the local service. 5. I’ll add three more classes to the project. I’m going to name the new classes AutoCompletionServiceProxy.cs, AutoCompletionServiceApplication.cs and AutoCompletionServiceApplicationProxy.cs respectively. 6. AutoCompletionServiceApplication inherits from SPIisWebServiceApplication and implements IFormattable. As a persisted object, the AutoCompletionServiceApplication class must be decorated with the System.Runtime.InteropServices.Guid attribute and assigned a unique guid. AutoCompletionServiceApplication overrides the abstract InstallPath and VirutalPath properties of its parent SPIisWebServiceApplication. AutoCompletionServiceApplication also overrides the ManageLink virtual property of SPServiceApplication. 7. AutoCompletionServiceApplication needs two methods to both provision and unprovision the service application and its instance. These methods will be called from the UI when an administrator creates or tears down a service application instance. 8. AutoCompletionServiceProxy inherits from SPIisWebServiceProxy and implements the IServiceProxyAdministration interface. IServiceProxyAdministration requires the GetProxyTypes, GetProxyDescription and CreateProxy methods to be implemented. Also of note, AutoCompletionServiceProxy is decorated with the SupportedServiceApplication attribute which tightly couples it to AutoCompletionServiceApplicationProxy. Refer to the accompanying sample project for the complete class listing. 9. AutoCompletionServiceApplicationProxy inherits from SPIisWebServiceApplicationProxy. 10. Add another class titled AutoCompletionServiceInstance.cs to your Visual Studio 2010 project. AutoCompletionServiceInstance inherits from SPIisWebServiceInstance. This class overrides the DisplayName and TypeName properties. Again, refer to the accompanying sample project for the complete class listing. 11. In SharePoint 2010, WCF web services are stored at the path [14 Hive]\WebServices. On most systems the full path to this location is C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\WebServices. In Visual Studio 2010, I’ll create a SharePoint Mapped Folder to this location by right-clicking on the AutocompleteDemo project in Solution Explorer and selecting Add > SharePoint Mapped Folder. Note the 14 hive’s WebServices folder at the bottom of the list. 12. Next, I’m going to expand the newly created WebServices mapped folder and right-click on the AutocompleteDemo folder below. From the context menu, I select Add > New Item. In the Add New Item dialog, I select the WCF Service template and name the new file YouCompleteMeService.cs. 13. I’m going to move the App.config file that was added automatically to be in the same folder as YouCompleteMeService.cs. Then I rename App.config to web.config and delete its contents. I’m going to create my own configuration file. In the web.config file I’ll turn on aspNetCompatibilityEnabled, define a default endpoint for our WCF service, and also turn on enableWebScript for AJAX compatibility. Refer to the accompanying sample project for the complete web.config listing. 14. For some reason, Visual Studio 2010 doesn’t automatically add a WCF Service Host declaration file to the SharePoint Project for me. At least in the VS2010 Beta, I’ll have to add this file manually. To do so, I just add another file to the AutocompleteDemo folder below WebServices mapped folder in the project. I select a Text file as the file type and name it YouCompleteMeService.svc. This Service Host file will only contain a few lines declaring the service and its factory. 15. I’m going to delete the YouCompleteMeService.cs, as I won’t be using it. 16. Now, I’ll add two more classes named AutoCompletionServiceApplicationHostFactory and AutoCompletionServiceApplicationHost to the root of the project. AutoCompletionServiceApplicationHostFactory inherits from ServiceHostFactory and overrides the CreateServiceHost method. 17. AutoCompletionServiceApplicationHost inherits from System.ServiceModel.ServiceHost and implements both the IFormattable and IDisposable interfaces. 18. Next, I expand the Features folder of the AutocompleteDemo Visual Studio project and rightclick on Feature1. From the context menu, I click Add Event Receiver. In the newly created Feature1.EventReceiver.cs class, only the FeatureActivated method is salient to this application. In the FeatureActivated method, I check to see if an AutoCompletionService object has ever been created, and if not create it. Only one local AutoCompletionService will ever be needed. After an AutoCompletionService has been created for the first time, SharePoint’s service application management will become aware of the new service application and allow administrators to create or manage instances of the Auto Completion Service Application from Central Administration. I’ll make the admin pages to create and manage our service application in Part 2. Part Two – the Service Application’s Admin Interface The Create and Manage Application Pages 1. In the project, I’ll add a SharePoint Mapped Folder to the [14 Hive]\TEMPLATE\ADMIN directory. 2. In Solution Explorer, I’m going to expand the newly created ADMIN mapped folder, right-click the AutocompletionDemo subfolder, and from the context menu Add > New Item. I select a SharePoint Application Page and name it ServiceCreate.aspx. Then, I repeat the process to add one more page named ServiceManage.aspx. 3. The ServiceCreate page will be a popup dialog box, and as such should be modified to inherit from SharePoint’s ~/_layouts/dialog.master master page. This page will implement place holders for its master page’s PlaceHolderDialogHeaderPageTitle , PlaceHolderDialogDescription and PlaceHolderDialogBodyMainSection content sections. Refer to the accompanying sample project for the complete listing. 4. Inside the PlaceHolderDialogBodyMainSection, I add the necessary controls to gather user input before creating the service application. This page will ask for the service application’s name, application pool identity, and a check box to set this instance as the default. 5. Inside the ServiceCreate page’s code-behind, within the CreateNewServiceApp method is where the new Auto Completion service application is actually created. All of the heavy lifting for creating the service application resides with a SPLongOperation. Refer to the accompanying sample project for the complete listing. 6. The ServiceManage page is where developer’s are free to add any user configurable settings for the service application. The Auto Completion service application has no user configurable options, so this page is largely left blank for the purposes of our demo. Note that this page’s master page is ~/_admin/admin.master. 7. At this point, the Auto Completion service application can actually be deployed to SharePoint, and instances of the service application can be provisioned in Central Administration. Of course, the application doesn’t actually do anything yet, but the core infrastructure pieces have been defined. To verify this, right-click on the AutocompleteDemo project in Solution Explorer and select Deploy. The solution will deployed, and after a few seconds, you should see a “Deploy succeeded” message in the bottom left corner of Visual Studio. 8. To verify deployment, I can open SharePoint’s Central Administration site and click on Manage service applications under the Application Management menu heading. 9. Selecting any item in the list of services will cause the Service Applications ribbon to appear. I’ll click the New button to see the Auto Complete Service Application list there. Now I can go ahead and click it to create a new service application instance. 10. If all is well, I’m presented with a dialog box to create a new Auto Completion service application instance. 11. Congratulations! If everything works on this next step, most of the hard part is over. I can go ahead and complete the form by entering an instance name and selecting an application identity. When finished, I click OK to provision the service application. If the provisioning succeeded, a pair of listings for the new service application and its proxy should now be available on the Manage Service Applications Page. I haven’t added any user configuration options for this demonstration, but clicking the listing’s link to will visit the ServiceManage page. 12. One more step to verify the provisioning was successful is to check that the service application’s virtual application was created in IIS. To do so, I can open Internet Information Services (IIS) Manager from Administration Tools on the Start menu of the Windows Server running SharePoint 2010. Next, I’ll expand the Sites node and then expand the SharePoint Web Services node below that. I right click on one of the virtual applications below SharePoint Web Services and select Switch to Content View. 13. I’m looking through the list of virtual applications which have guids for names. Notice SharePoint’s built-in service applications such as MetadataWebService.svc and WebAnalyticsService.svc. I’m looking for the virtual application with a guid for a name that that contains our Service Host file YouCompleteMeService.svc. If everything checks out, the empty WCF service has been provisioned. Part Three – The WCF Service Endpoint 1. In this step, I’ll revisit the AutoCompletionServiceApplication class. In order for this class to provide ASP.NET AJAX auto completion services, I’ll start by decorating it with the AspNetCompatibilityRequirements attribute. 2. Next, I cause AutoCompletionServiceApplication to implement the IYouCompleteMeService interface and its required methods. These methods will provide auto-completion data to the AJAX-enabled input controls I’ll create in the next step. 3. Note that I’ve created a helper class to handle supplying data to the service methods. The actual data resides in a simple, albeit lengthy text file. CitiesHelper reads said data and performs simple Linq queries to filter on the correct city and state names. CiteiesHelper uses a singleton pattern to avoid excessive file I/O and memory usage. In a real-world production scenario, a more robust SQL database to house this data could have been provisioned along with the Service Application. However, for the purposes of this demonstration a simple text file will do fine. Refer to the accompanying project for the complete CitiesHelper code listing. Part Four – The User Application Page Download the ASP.NET AJAX Control Toolkit 1. The ASP.NET AJAX Control Toolkit is an open-source project built on top of the Microsoft ASP.NET AJAX framework. It is a joint effort between Microsoft and the ASP.NET AJAX community that provides a powerful infrastructure to write reusable, customizable and extensible ASP.NET AJAX extenders and controls, as well as a rich array of controls that can be used out of the box to create an interactive Web experience. I’m going to use the toolkit’s AutoCompleteExtender to transform a plain old SharePoint InputFormTextBox into an AJAX enabled overnight sensation! a. I’ll create a folder called Dependencies in the same directory as the Visual Studio solution file. I’ll need to download the ASP.NET AJAX Control Toolkit binaries from this URL and add the AjaxControlToolkit.dll to the Dependencies folder. b. http://www.asp.net/ajax/downloads/ Add a New Project and Test Page 2. In Visual Studio, I’m going to add a new SharePoint Empty Project to the solution and name it AutoCompletionDemoTest. This time, I’m sure to target a regular SharePoint content application (not Central Admin as before) from the SharePoint Customization Wizard. 3. I add a reference to the downloaded AjaxControlToolkit.dll from the AutoCompletionDemoTest project. 4. Next, I add a reference to System.Web.Extensions .NET framework assembly from the AutoCompletionDemoTest project. 5. I also add a project reference to the AutoCompletionDemo project from the AutoCompletionDemoTest project. 6. The AutoCompletionDemo project is only going to contain one test page. I’m going to add a new SharePoint Application page to the project and name it appropriately enough Test.aspx. 7. The main content section of Test.aspx is going to contain a placeholder for the map along with text input boxes for the user to key-in city and state names. 8. Test.aspx also contains a few Javascript methods to help with retrieving and formatting the map control based on users’ city and state input. 9. In code-behind file Test.aspx.cs is where I’m going to add control extenders for the page’s two text input controls. These extenders will handle communicate with the WCF service’s GetStates and GetCitiesForState web methods to provide suggested auto-completion data. 10. To tie everything together, I’ll also add a GetServicesEndpointPath helper method the test page’s code-behind. This method will go through the Auto Completion Service Application’s proxy to determine the default service endpoint. Bringing It All Together 1. From Visual Studio, I’m going to re-deploy the AutocompleteDemo service application project to Central Admin to ensure the WCF endpoint’s logic is in place. 2. Next, I’ll deploy the AutocompleteDemoTest test project to a SharePoint content application. 3. To see the end result, I can browse to Test.aspx in my SharePoint Content Application by visiting the URL: a. http://[myserver]/_LAYOUTS/AutoCompletionDemoTest/test.aspx