Create a Custom Control to Wrap the Google JSON/ATOM Custom Search API, Part 2

Add design-time features to the GoogleRestApiControl custom control created in part 1

Bipin Joshi

August 3, 2011

11 Min Read
Two men with a computer and a tablet

In Part 1 of this article, we learned the basics of the Google JSON/ATOM Custom Search API and also developed an ASP.NET custom server control to wrap the API for easy use in our web applications. In this part we will add design-time features to the GoogleRestApiControl custom control, such as Smart-tag and custom drop-down lists. In the process, we will discuss how to create a custom control designer, a custom action list, and a custom type converter for our custom control.

As a quick recap, the properties and methods of the GoogleRestApiControl are listed again in Figure 1.

Property / Method

Figure 1: Properties and methods of GoogleRestApiControl

Url

ApiKey

CustomSearchEngineId

SearchCriteria

LanguageFilter

SafeSearchOption

FilterDuplicateResults

SearchResultFormat

ClientCallbackName

GetSearchResults()

GetSearchResultsAsSyndicationItems()

GetClientScriptBlock()

The LanguageFilter property of the GoogleRestApiControl specifies the language restriction for the search results. There are several languages supported for this property such as lang_en (English), lang_fr (French), and lang_de (German). It would be useful to present a list of frequently used language options to the developer using our control, to make it easy to configure the LanguageFilter property. We can accomplish this with the help of a TypeConverter. A TypeConverter provides a way to convert property values from one type to another and also provides a way to access standard values.

In order to create a TypeConverter, we need to create a class that inherits from TypeConverter base class and then override certain methods. So, we need to add a new class to our custom control project and name it SupportedLanguageList. Figure 2 shows the SupportedLanguageList class, which acts as a custom TypeConverter for LanguageFilter property.

The SupportedLanguageList class overrides these four methods: GetStandardValuesSupported(),GetStandardValues(),CanConvertFrom(), and ConvertFrom(). The GetStandardValuesSupported() method indicates whether the property supports a standard set of values that can be picked from a list. We return true since we want to provide this feature. The GetStandardValues() method returns a list of standard values in the form of StandardValuesCollection. We return three standard values, namely lang_en, lang_fr, and lang_de. The CanConvertFrom() method indicates whether our type converter can convert a value of one type to the type of this converter. The type of the converter and the data type of the target property (LanguageFilter) must match. We return true only if string values are entered. Finally, ConvertFrom() method actually converts the value if required.

Once we've created our custom type converter, it can be used on the LanguageFilter property, as shown in Figure 3.

The [TypeConverter] attribute specifies the type of a converter class for the property under consideration. Thus for LanguageFilter property SupportedLanguageList class will act as a type converter. After applying the [TypeConverter] attribute the LanguageFilter property will render a pick list in the Properties window, as shown in Figure 4. Note that in addition to the standard values we can also enter a value manually.

In order to add smart-tag support to our GoogleRestApiControl, we need to create a custom action list class and a control designer class. A custom action list class inherits from the DesignerActionList base class and defines a list of items used to create the smart tag.

To create a custom action list class, add another class to the custom control project and name it GoogleRestApiActionList. Figure 5 shows a part of the GoogleRestApiActionList class.

The GoogleRestApiActionList class inherits from DesignerActionList base class and declares two class level variables, one of type GoogleRestApiControl and the other of type DesignerActionUIService. The DesignerActionUIService class is a .NET Framework class that manages the user interface for smart tags. The constructor of the GoogleRestApiActionList class initializes these two variables to appropriate values.

The GoogleRestApiActionList class then defines properties that essentially wrap the corresponding properties of the GoogleRestApiControl class. We need to define only those properties that we want to include on the smart tag. We won't discuss these properties here, as they are just simple wrappers over the existing properties.

Once the properties of the GoogleRestApiActionList class are ready, we need to override the class's GetSortedActionItems() method to specify the items appearing on the smart tag. Figure 6 shows the complete code for the GetSortedActionItems() method.

Figure 7 shows the smart tag.

The return type of the GetSortedActionItems() method is DesignerActionItemCollection. We have used three types of action items for our smart tag: header, static text, and property. The DesignerActionHeaderItem class represents a header for an action list section (e.g., API, Search, Client Script). The DesignerActionTextItem class represents a static text item (e.g., URL to Google's custom search engine website). The DesignerActionPropertyItem class represents a property that is to be displayed on the smart tag. While defining items of type DesignerActionPropertyItem, we can specify the details such as the property name, its prompt text on the smart tag, its category on the smart tag, and the item's description.

Our job doesn't end here. We now need to create a control designer class that inherits from the ControlDesigner base class and governs the design-time behavior of the control. The control designer attaches thesmart tag with the custom control and also defines the design-time look and feel of the control. Our control designer class (GoogleRestApiControlDesigner) will look like that shown in Figure 8.

The GoogleRestApiControlDesigner class defines a class level variable of type DesignerActionListCollection. The overridden ActionLists property creates and returns an instance of the GoogleRestApiActionList class (i.e., our smart-tag class). We also override the GetDesignTimeHtml() method and define HTML markup that governs the design-time look and feel of our control, as shown in Figure 9.

The last step is to decorate the GoogleRestApiControl class with the [Designer] attribute and specify the control designer type to use. Doing so will attach our custom designer with the GoogleRestApiControl class. Figure 10 shows a fragment of related code.

Now that we have finished building our custom control, let's use it on a web form and test its functionality.

Add a new website to the same solution and open the default web form. Visual Studio automatically adds our custom control on the Toolbox (see Figure 11).

Note that this is displayed in the Toolbox because a reference has been added to the GoogleRestApiControlLib in the /bin directory. Now design the default web form, as shown in Figure 12.

The web form consists of an instance of GoogleRestApiControl, a Label, a TextBox, and a DataList control. Using the Properties window or the smart tag, set various properties of the GoogleRestApiControl control so that the server-control markup resembles the code in Figure 13.

Make sure to substitute xxxx inFigure 13 with your own API key and custom search engine ID, respectively. The Search button's click event handler programmatically searches the specified custom search engine and displays the search results in a DataList, as shown in Figure 14.

Notice how the SyndicationItem class's properties are bound with various server control properties. Figure 16 shows a sample run of the web form.

This "server-side" searching can be very useful in certain situations. Suppose we are building a content-rich website, and, while displaying an article we also want to show a list of related articles. You can achieve this by performing a search using a Google custom search engine with the article keywords (or tags) in the server-side code, then displaying the results along with the article as a sidebar or footer.

Similarly, you can also test the client-side handling of the search results. Though we won't discuss it here, the code download accompanying this article contains sample jQuery code that illustrates client-side handling of the search results.

Google's JSON/ATOM custom search API allows us to search custom search engines using the REST programming model. Wrapping the API in a custom control makes it easy to use without requiring you to know the API's internals. You can further enhance the custom control by adding the following features:

Bipin Joshi has been programming since 1995 and has worked with .NET since its inception. He has authored or coauthored several books and numerous articles on .NET technologies. Bipin blogs on yoga and technology at bipinjoshi.com.

Read more about:

Alphabet Inc.
Sign up for the ITPro Today newsletter
Stay on top of the IT universe with commentary, news analysis, how-to's, and tips delivered to your inbox daily.

You May Also Like