The Definitive Hello World Custom Research Service Tutorial

This content is no longer actively maintained. It is provided as is, for anyone who may still be using these technologies, with no warranties or claims of accuracy with regard to the most recent product version or service release.

Summary: The Research Service in Microsoft Office 2003 applications turns the Research task pane into a powerful search experience that can directly connect search-result data with documents. While the Microsoft Office System comes with some Research providers already registered and ready for use, you can create your own custom research services. This article explains how reference libraries work and how to create your own custom service. (12 printed pages)

John R. Durant, Microsoft Corporation

November 12, 2003

Applies to: Microsoft Office Word 2003, Microsoft Office System

Contents

  • The Business Scenario

  • Research Feature Overview

  • Registration and Query Web Methods

  • Conclusion

The Business Scenario

It is always a good idea to understand what value a given feature or technology presents. The Research task pane in the Microsoft Office System simply lets users search for data. Of course, this can be done elsewhere in other ways. What makes this search environment unique is that it is tightly connected with the user's experience in an Office application. Figure 1 shows the task pane using one of the providers that comes with the Microsoft Office System right out of the box. Instead of copying and pasting terms from a document into another application or form to do a search, a user can place document text automatically in the Research task pane. This makes it easier for users to search on terms right where they work. Similarly, after a search returns results, a user does not need to copy and paste result data from a separate form or application into the target document. The Research task pane supports special programmable actions so that you can place result data directly in a document, in the right place, and even in the right format.

Figure 1. The Research task pane gives users quick access to useful data.

The advantage for users to avoid moving back and forth between applications is considerable. But, the fact that you can create your own research service - one customized to the specific needs of a company, department, or team - is even more appealing. In addition, because the Research task pane supports smart tag action handlers, you can create your own handlers to do other timesaving tasks for users. You can use the smart tag actions to take data from the Research task pane and do an infinite number of other customized activities such as embedding data in documents, automating other Office applications, sending e-mail messages, and so forth.

Research Feature Overview

This article, while not actually using the words "Hello World" is designed to be an introduction for those who want to know how to get a very basic custom Research provider up and running. Let's first look at the overall architecture. The Research Service in the Microsoft Office System is classic client/server architecture. The client application is the Office 2003 application and the server-side portion is a Web service that fields search requests and sends back responses. End-users, of course, are unaware of any of this, and the Research task pane is where they interact with the Web service. Figure 2 below shows the general architecture of the Research feature.

Figure 2. Architecture of Research Services

Figure 3. Users can choose from a list of built-in or custom providers

Perhaps the most important part of the entire architecture is what makes it possible for a Web service to be used by the Microsoft Office System. In other words, if the Web service does most of the work - receiving requests and returning responses - there must be something that tells the Office application that the Web service is specifically designed to field requests from it. So, not just any Web service will do. The Web service and Office must have a shared understanding about how requests and responses are packaged up, how they are sent, and what they can contain. This mutual understanding is made possible through XML schemas.

The XML schemas are, in effect, contracts between the Office application and the Web service about how they communicate with one another. After a user defines the search criteria in the user interface (UI) and submits the search request, the Office application packages the request using the structure, data types, and other prescriptions of an XML schema. Then, the Office application sends the packaged request to the Web service using SOAP messages. The Web service, because it expects the message to be sent using SOAP and in a manner conforming to the schema, can unpack the request and handle it in whatever way you, the developer, define. Then, the Web service assembles a response, packages it according to the schema, and sends it back to the Office application using a SOAP message. The Office application can then unpack the response and display the results in the task pane.

This request/response exchange occurs for every search request a user initiates. It also occurs even before a user begins a search, as Office needs to communicate with the Web service to register it on the client computer and make sure it is available for use. A user can register the Research provider in the UI, or you can do this programmatically. Either way, the Office application needs to contact the Web service and make sure it can use it as part of the Research feature. To understand more fully how registrations and search queries work, let's take a closer look at the Web methods that the Office application calls when contacting the Web service.

Registration and Query Web Methods

To create your own custom provider, you need to create a Web service. This is most easily done creating an ASP.NET Web service using Microsoft Visual Studio .NET 2003, but you can create one using Microsoft Visual Studio .NET 2002 or you can create a SOAP-compliant Web service using COM technology. Going into the details of how to create a basic Web service in Visual Studio goes beyond the scope of this article as this task is documented elsewhere. Your service provides two Web service URLs - one for registration, and one for queries, with each exposing one Web method.

Note

For more information about how to create a ASP.NET Web service, see Creating XML Web Services in Managed Code.

Before a user can start executing queries against your custom Research provider the Office application needs to know about it. This is known as registration, and it consists of the Office application sending a request to the Web service and the Web service sending back a response with a special set of data. These data contain details that the Office application then stores in the registry. The Research providers are then found in the list of providers available to end-users as shown in Figure 2 above.

A user can type the address of the provider in the UI and the Web service returns information about the Research service packaged up in XML as shown in Figure 3.

Figure 4. Users can type the URL for a custom provider

This following XML is the response from the custom provider:

<?xml version="1.0" encoding="utf-8"?>
<ProviderUpdate xmlns="urn:Microsoft.Search.Registration.Response">
   <Status>SUCCESS</Status>
    <Providers>
      <Provider>
        <Message>Registered</Message>
        <Id>{5A1AAF54-87F0-4f1d-A2D4-AB3E5D080DE1}</Id>
        <Name>Northwind Data Research Pane</Name>
        <QueryPath>http://localhost/nwindrr/query.asmx</QueryPath>
        <RegistrationPath>http://localhost/nwindrr/registration.asmx
         </RegistrationPath>
        <AboutPath>http://localhost/nwindrr/about.aspx</AboutPath>
        <Type>SOAP</Type>
        <Services>
          <Service>
            <Id>{1698075D-E2F5-4254-87B2-7FC9E9AB0780}</Id>
            <Name>Northwind Source Data</Name>
            <Description>Acquire Northwind Information</Description>
            <Copyright>All content Copyright (c) 2003.</Copyright>
            <Display>On</Display>
            <Category>INTRANET_GENERAL</Category>
            </Service>
        </Services>
      </Provider>
    </Providers>
</ProviderUpdate>

The key is that the Microsoft Office System expects this XML to be constructed in a certain way. The elements must be in a specific order, have prescribed names, and comply with certain data constraints. After the XML is received, the Office application can register the Research provider such that it is available for users to access. Registration includes recording some information in the registry. For example, the data in the previous XML example are from an actual Research provider response. After successful registration, this data can be found in the following location:

HKEY_CURRENT_USER\Software\Microsoft\Office\11.0\Common\Research\Sources

This key in the registry contains a list of the various Research providers to which the Office application can connect, each provider listed by using a special ID. Figure 4 shows some of the data from the registry for the custom Research provider used in this article.

Figure 5. The registry holds information about registered Research providers

For your Research service to enable registration, your Web service must expose a method called Registration. The following example shows an implementation of this method:

public string Registration( string registrationXml) 
{
XmlDocument xdResponse = new XmlDocument();
try 
{
 string httpPath = 
    ConfigurationSettings.AppSettings["ServerPath"].ToString() 
    + HttpContext.Current.Request.ApplicationPath + "/";
 xdResponse.Load(helpers.GetCurrentPath() + 
    "\\xml\\RegistrationResponse.xml");
 XmlNamespaceManager nsm = 
    new XmlNamespaceManager(xdResponse.NameTable);
 nsm.AddNamespace("ns", 
    "urn:Microsoft.Search.Registration.Response");
 xdResponse.SelectSingleNode("//ns:QueryPath", nsm).InnerText = 
    httpPath + "query.asmx";
 xdResponse.SelectSingleNode("//ns:RegistrationPath", nsm).InnerText = 
    httpPath + "registration.asmx";
 return xdResponse.InnerXml;
} 
catch
{
 return "";
}

Most of this code is concerned with loading an XML file on the Web server that serves as a template for the method's return value. The code retrieves the Web server's name from the appSettings section of the Web.config file and uses this to create URL paths for the QueryPath and RegistrationPath sections of the Web method's response. These paths are important because after the Research provider is registered, these paths are the ones that the Office application uses when updating the registration or querying the Web service.

You do not need to use a template for the registration response as is done here, but it is useful to avoid constructing the XML file from scratch every time the registration method is called. The entire contents of the template file is as follows:

<?xml version="1.0" encoding="utf-8"?>
<ProviderUpdate xmlns="urn:Microsoft.Search.Registration.Response">
   <Status>SUCCESS</Status>
   <Providers>
      <Provider>
         <Message>This is a sample research library</Message>
         <Id>{5A1AAF54-87F0-4f1d-A2D4-AB3E5D080DE1}</Id>
         <Name>Sample Research Library</Name>
         <QueryPath/>
         <RegistrationPath/>
         <AboutPath/>
         <Type>SOAP</Type>
         <Services>
            <Service>
               <Id>{1698075D-E2F5-4254-87B2-7FC9E9AB0780}</Id>
               <Name>Sample Research Library</Name>
               <Description>This is a sample research
 library</Description>
               <Copyright>All content Copyright (c) 2003.</Copyright>
               <Display>On</Display>
               <Category>RESEARCH_GENERAL</Category>
            </Service>
         </Services>
      </Provider>
   </Providers>
</ProviderUpdate>

For more information about each element in the schema for a Registration response, see the Microsoft Office Research Service 2003 Software Development Kit (SDK). However, there are two elements merit mentioning here. These are the <Id> elements - one in the <Provider> element and the other in the <Service> element. These elements contain globally unique identifiers (GUIDs) that are assigned to the Research provider and its underlying Web service. These identifiers must be unique, and you can use a tool such as guidgen.exe to create them.

Note

Guidgen.exe is included as part of Microsoft Visual Studio .NET 2002 or Visual Studio .NET 2003. When using it, you choose the format in which the GUID is expressed so you don't have to retype it. For more information on the Guidgen tool, see the Knowledge Base article 168318 XADM: Guidgen.exe Available Only for Intel Platforms.

Once the Web service is registered, a user can submit queries to the Research service in an Office application. From the UI, users can specify search criteria (shown in Figure 5 later in this article) and submit the query. The Office application then makes a call to the Research service by accessing the query.asmx Web service. This service exposes a method called Query that accepts one parameter, queryXml,and returns a string. ThequeryXmlparameter contains well-formed XML with the user's search criteria. The following example shows the contents of the queryXml argument as passed to the Query method when the user searches for the keyword "food":

<QueryPacket xmlns='urn:Microsoft.Search.Query' revision='1' build='(11.0.5329)'>
  <Query domain='{1698075D-E2F5-4254-87B2-7FC9E9AB0780}'>
    <QueryId>{AE4CDA59-C3EC-496A-B0B3-B21A55EEA0CC}</QueryId>
    <OriginatorId>{F6FF7BE0-F39C-4ddc-A7D0-09A4C6C647A5}</OriginatorId>
    <SupportedFormats>
      <Format revision='1'>
urn:Microsoft.Search.Response.Document:Document</Format>
      <Format revision='1'>
urn:Microsoft.Search.Response.Content:Content</Format>
      <Format revision='1'>
urn:Microsoft.Search.Response.Form:Form</Format>
     </SupportedFormats><Context>
    <QueryText type='STRING' language='en-us' >food</QueryText>
    <LanguagePreference>en-us</LanguagePreference>
    <Requery></Requery></Context>
    <Range id='result'></Range>
    <OfficeContext 
xmlns='urn:Microsoft.Search.Query.Office.Context' revision='1'>
      <UserPreferences>
       <ParentalControl>false</ParentalControl>
      </UserPreferences>
      <ServiceData></ServiceData>
      <ApplicationContext>
        <Name>Microsoft Office Word</Name>
        <Version>(11.0.5329)</Version>
        <SystemInformation>
          <SkuLanguage>en-us</SkuLanguage>
          <LanguagePack>en-us</LanguagePack>
          <InterfaceLanguage>en-us</InterfaceLanguage>
          <Location>US</Location>
        </SystemInformation>
      </ApplicationContext>
      <QueryLanguage>en-us</QueryLanguage>
      <KeyboardLanguage>en-us</KeyboardLanguage>
   </OfficeContext>
   <Keywords 
xmlns='urn:Microsoft.Search.Query.Office.Keywords' revision='1'>
    <QueryText>food</QueryText>
    <Keyword><Word>food</Word></Keyword>
   </Keywords>
  </Query>
</QueryPacket>

The Query method fields the search request from the Office application and returns a result. As you might guess, the structure of the XML in the queryXml argument and the structure of the XML sent back to the Office application must conform to schemas, just as the registration request and response also conformed to well-defined schemas. The operations occurring after the query request is received by the Research service are concerned with getting the search keywords, doing something with them, and structuring a response so that the Office application can give the user a search result.

The full implementation for the Query method in this article is as follows:

public string Query(string queryXml)
  {
    if ( queryXml.Length == 0 )
    {return "";}
    string  queryString;
    //Get current physical path
    string  physicalPath = GetCurrentPath();
    XmlDocument  requestXml = new XmlDocument();
    //Load the queryXml into an XmlDocument
    requestXml.LoadXml(queryXml.ToString());
    //Add necessary namespaces
    XmlNamespaceManager  nsmRequest = 
      new XmlNamespaceManager(requestXml.NameTable);
    nsmRequest.AddNamespace("ns", 
      "urn:Microsoft.Search.Query");
    nsmRequest.AddNamespace("oc", 
      "urn:Microsoft.Search.Query.Office.Context");
    //Get the actual search terms
    queryString = requestXml.SelectSingleNode("//ns:QueryText", 
      nsmRequest).InnerText;
    //Load some pre-configured XML for the response
    XmlDocument responseWrapper = new XmlDocument();
    responseWrapper.Load(physicalPath + 
      "\\xml\\ResponseWrapper.xml");
    XmlNamespaceManager nsmResponse =
      new XmlNamespaceManager(responseWrapper.NameTable);
    nsmResponse.AddNamespace("ns", 
      "urn:Microsoft.Search.Response");
    nsmResponse.AddNamespace("rc", 
      "urn:Microsoft.Search.Response.Content");
    //Get the list of customers matching search term
    customerData = GetCustomersList(queryString);
    //Take the resulting customerData XML and put in response
    responseWrapper.SelectSingleNode("//ns:Range",
      nsmResponse).InnerXml =customerData;
    return responseWrapper.InnerXml;
  }

The main point of the code for this method is to get the search term and do something with it. In this example, the search term is submitted to another custom procedure, GetCustomersList. This procedure creates a portion of the final response that is returned by the Query method. Whatever the GetCustomersList procedure returns is placed within a specific node of the total response returned to the Office application from the Research service.

The GetCustomersList code embeds an image and then calls another procedure that goes to the database, executes a stored procedure, and returns a SqlDataReader object. After some basic formatting output, the code loops through the list of customers, adding some formatting tags to the company names.

private string  GetCustomersList( string  queryTerm) 
{
  StringWriter queryResponse=new StringWriter();
  XmlTextWriter  outputXmlWriter = new XmlTextWriter(queryResponse);
  SqlDataReader customerReader;
  //Use custom procedure to go to database and get list of customers
  //Put the returned list of customers in an SqlDataReader
  customerReader = DBGetCustomersList(queryTerm);
  outputXmlWriter.WriteStartElement("Results");
  outputXmlWriter.WriteStartElement("Content",
    "urn:Microsoft.Search.Response.Content");
  //Insert image for Northwind
    outputXmlWriter.WriteStartElement("Image");
  //Get the http path to the image from a variable
  outputXmlWriter.WriteAttributeString("source", 
    httpPath + "Images/nwind_small.jpg");
  outputXmlWriter.WriteEndElement();
  outputXmlWriter.WriteStartElement("P");
  outputXmlWriter.WriteStartElement("Char");
  outputXmlWriter.WriteAttributeString("Font","arial");
  outputXmlWriter.WriteAttributeString("smallCaps","true");
  outputXmlWriter.WriteAttributeString("bold","true");
  outputXmlWriter.WriteString("Customers with '" + 
    queryTerm + "' in their name");
  outputXmlWriter.WriteEndElement();
  outputXmlWriter.WriteEndElement(); //Search term 
  //Insert a separator line before listing the customers
  outputXmlWriter.WriteElementString("HorizontalRule", "");
  //Begin listing the actual customers
  while ( customerReader.Read())
  {
    //Begin Company Name
    outputXmlWriter.WriteStartElement("P");
    outputXmlWriter.WriteStartElement("Char");
    outputXmlWriter.WriteAttributeString("font","times");
    outputXmlWriter.WriteAttributeString("light","true");
    outputXmlWriter.WriteString(customerReader["CompanyName"].ToString());
    outputXmlWriter.WriteEndElement(); 
    outputXmlWriter.WriteEndElement();
    //End Company Name
  }
  outputXmlWriter.Close();
  return queryResponse.ToString();
}

Finally, the GetCustomersList procedure returns a string that can be placed in the final response the Research service returns to the Office application. The full XML of a response looks like this:

<?xml version="1.0" encoding="utf-8"?>
<ResponsePacket revision="1" xmlns="urn:Microsoft.Search.Response">
  <Response domain="{1698075D-E2F5-4254-87B2-7FC9E9AB0780}">
    <Range>
      <Results>
        <Content xmlns="urn:Microsoft.Search.Response.Content">
          <Image source=
           "http://localhost/nwindrr/Images/nwind_small.jpg"/>
          <P><Char Font="arial" smallCaps="true" bold="true">
          Customers with 'mer' in their name</Char></P><HorizontalRule />
          <P><Char font="times" light="true">Centro comercial        
           Moctezuma</Char></P>
          <P><Char font="times" light="true">LILA-Supermercado</Char></P>
          <P><Char font="times" light="true">Romero y tomillo</Char></P>
          <P><Char font="times" light="true">Tradição 
            Hipermercados</Char></P>
        </Content>
      </Results>
    </Range>
  <Status>SUCCESS</Status>
 </Response>
</ResponsePacket>

The corresponding user experience in the task pane for this XML is shown in Figure 5. Because this article is designed to be introductory, it does not present a more elaborate and useful user experience. Ultimately, you can craft the Research task pane so that users can do research and quick reference tasks and view the results in the task pane side by side with the document.

Figure 6. The results returned from the custom provider formatted for the Research task pane

Furthermore, the Research feature in the Microsoft Office System lets you, as a developer, add special actions to the information returned by your Research service. These custom actions are presented to information workers using smart tags. A smart tag action handler can allow users to perform different tasks, such as giving them the ability to grab additional content, transform the response text, or launch an application. Another type of action can place content into Microsoft Office Word 2003 and Microsoft Office Excel 2003 documents as XML, and then, for example, additional intra-document actions may become available.

Conclusion

The Research Service in the Microsoft Office System can significantly improve the power the users wield when working in an Office application. They can search, re-query, and have complicated tasks automatically include search result data through the Research task pane. As a developer, you have the opportunity to craft a Research and Reference provider that is tailored to the specific needs of your organization, or even for a small department or team. Custom research services are not difficult to create, and once you understand the schemas that are shared between Office and your provider, you become a key player in helping users get more done and have a more pleasant time doing it.

About the Author

John R. Durant manages the MSDN Office Developer Center whose mission is to help developers use the latest and greatest technologies in Office and to provide documentation for previous versions. If he could, he would rent the space in this bio.