OpenSearch in ASP.NET MVC

I got tired of referring to my codecamp presentation every time I wanted to do another implementation of OpenSearch so I figured I would write it down.

What is Open Search

OpenSearch is using that search bar that is built into most browsers. Google Chrome uses the address bar. Internet Explorer has a separate textbox for searching. This is defaulted to your default search engine that is setup when you run your browser for the first time, but you can have your browser search other sites if you tell it to. If you go to a site like Amazon and click the down arrow for your search textbox (in IE) you will see the search providers configured for Amazon.com.

This stuff is easy to write, even if you have never even heard of OpenSearch before. It will literally take you 5 minutes to get running. So let's do it!

Step 1

Do not go to OpenSearch.org because it will only give you confusion and heartache.

Step 2 and Beyond

Create a new XML file in the content folder of your site and call it OpenSearch.xml. Here is the contents of my file.

<?xml version="1.0" encoding="UTF-8" ? />
<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
    <ShortName>My Site's Asset Finder</ShortName>
    <Description>Find all your assets</Description>
    <Url type="text/html"
        method="get"
        template="http://MySite.com/Home/Search/?q=searchTerms"/>
    <InputEncoding>UTF-8</InputEncoding>
    <SearchForm>http://MySite.com/</SearchForm>
</OpenSearchDescription>

Nothing fancy here, but you wouldn't know how to write it without looking it up. It is OpenSearch specific but the elements are easy to fill in. ShortName and Description just write in whatever you want the browser to show. The Url template needs to be your site and point to the action you want it to go to. Alternatively you could write a route that corresponds to the Url you are supplying here. You will also want to supply a search terms parameter to your Url so that the action will be able to filter the results.

Next, you need to link to this XML file in your master page. In site.master, add the link to the header and change some of the attributes to suit your needs.

<link href="<%= Url.Content("~/Content/OpenSearch.xml") %>"
    rel="search"
    title="My Site's Asset Finder"
    type="application/opensearchdescription+xml" />

The type is another one of those things you are not going to remember. Now that your site has a reference to the xml file and knows how to search your site, all you have to do is implement the action that you promised would be there.

Implementing the Action

In your Home controller (or whatever you defined in your OpenSearch.xml) create a Search action that can return a view filtering the results with the given query string.

public ActionResult Search(string q)
{
    var assets = _assetRepository.FindAll()
        .Where(m => m.Name.Contains(q))
        .OrderBy(m => m.Name.IndexOf(q));

    var model = new SearchViewModel
    {
        Assets = assets,
        SearchTerm = q
    };
    return View(model);
}

I just wrote a linq query to pull all the assets out of my repository where the asset's name contains the search term and order the results so that the closest matches are first.

In my example I am also creating a view model called SearchViewModel that is just a container class that holds my asset objects and remembers my search term.

Creating the Search View

The last thing you need to do is implement the view you are calling in the Search action. This is where you can write your implementation specific code. It will be strongly typed to whatever structure you use to hold your search results. Mine was SearchViewModel and this is what I have in my search view.

<h3>
    Found <%: Model.Assets.Count().ToString() %> results for "<%: Model.SearchTerm %>".
</h3>

<% foreach (var asset in Model.Assets) { %>
    <div class="search-result">
        < %: asset.Name % >
    div>
<% } %>

This is just a basic implementation but now that you have a template you can make it whatever you want.

Build. Run.

Testing in Internet Explorer

Internet Explorer is actually easier to work with OpenSearch than others are (weird, I know). Go to your site and you will see that the drop down on the search bar is glowing red/orange. If you click it, you will see your search provider! Click on the provider and anything you type into your search bar will be your query string parameter to your action method. Now if you enter in "Bacon" as your search term (as I often do), you will get a view of all assets with the word "Bacon" in the name.

Pretty sweet, or is it savory?

You can also set your site's search provider to be your default search provider. This will get you some added benefits when browsing. You can get buttons to search your site anytime you select text in Internet Explorer. You can also use the search bar to search your site even if you are not at your site.

Testing in Google Chrome

Since Chome does not have a search textbox, it does not have a glowing dropdown button to select your new search provider. You need to be pretty direct with it and add the search provider. Right click the address bar and go to "Edit Search Engines" Add a new one. I'll call mine Content Finder. The keyword is going to be "Content" and the Url is the same as how I defined it in my OpenSearch.xml file only you add a %s where the search term should go. Mine looks like this:

http://www.MySite.com/Home/Search/?q=%s

Now when you type "asset" in your address bar you will see Chrome recommend your search provider. You can tab to select it and start typing your query string. Chrome will insert the query string where you dropped %s in the Url.