Some stuff about Web and .NET development
RSS icon Email icon Home icon
  • Implementing the Bing API in a ASP.NET website (part 2)

    Posted on July 22nd, 2009 Thibaut 7 comments

    In my last post, we saw how to get started with the Bing API. But the MSDN code is lacking (intentionally) from the following things that you might find useful :

    • You want to use Bing from a website and not from a console application
    • You want to use Bing to search on a particular website and not the whole web
    • You might want to handle the different kinds of errors/informations the right way
    • Some paging would also be very useful to browse the results
    • And maybe simplifying the code, extracting constants to ease their setup

    That’s what we’re gonna see here by taking a look at my implementation. Let’s see what the code is all about, then we’ll discuss about it. The code will be splitted in several parts, so we can discuss about it step by step.

    1. Extracting hardcoded values into constants

    public partial class SearchResults : Page

    {

        private const string BingApplicationId = "YourAppIDHere";

        private const string WebsiteToSearch = "http://www.thibautvs.com";

        private const int MaxResultsCount = 50; // Max value : 50 (Bing API v2.0)

        private const int PageSize = 10;

        private const string SearchLanguage = "en-US";

        private const bool HighlightText = true;

        private const string BingApiVersion = "2.0";

    First, I extracted all the hardcoded values in the code into constants. That’s way easier to setup the values. I also added one which enables you to easily activate/deactivate text highlighting of the keywords in the search result and the PageSize constant to take into account the paging functionality. From experience, I noticed that the BingService throws a SoapException when the ResultsCount is too large. By experimentation, I noticed that the value must be max 50. You can take a look at the MSDN to get more info about this restriction.

    2. Initializing the search request

    protected void Page_Load(object sender, EventArgs e)

    {

        this.dpgSearchResultsPager.PageSize = PageSize;

        InitializeSearchResults();

    }

    In the Page_Load, we initialize the PageSize of our pager (which is a DataPager bound to a ListView in the aspx page) and call the InitializeSearchResults() method.

    private void InitializeSearchResults()

    {

        using (BingService service = new BingService())

        {

            try

            {

                SearchRequest request = BuildRequest();

                SearchResponse response = service.Search(request);

                DisplayResponse(response);

            }

            catch (System.Web.Services.Protocols.SoapException ex)

            {

                DisplayErrors(ex.Detail);

            }

            catch (System.Net.WebException ex)

            {

                Console.WriteLine(ex.Message);

            }

        }

    }

    Tthe InitializeSearchResults method makes use of the BingService, which implements the IDisposable interface (thus, used here with the using keyword) in order to :

    1. Initialize the search request
    2. Get a search response
    3. Display the response
    4. Handle a SOAP exception, if there is one
    5. Handle a network exception, if there is one

    private SearchRequest BuildRequest()

    {

        SearchRequest request = new SearchRequest();

     

        // Common request fields (required)

        request.AppId = BingApplicationId;

        request.Query = Request.QueryString["keyword"] + string.Format(" (site:\"{0}\")", WebsiteToSearch);

        request.Sources = new SourceType[] { SourceType.Web };

     

        // Common request fields (optional)

        request.Version = BingApiVersion;

        request.Market = SearchLanguage;

        request.Adult = AdultOption.Moderate;

        request.AdultSpecified = true;

        request.Options = new SearchOption[] { SearchOption.EnableHighlighting };

     

        // Web-specific request fields (optional)

        request.Web = new WebRequest();

        request.Web.Count = MaxResultsCount;

        request.Web.CountSpecified = true;

        request.Web.Offset = 0;

        request.Web.OffsetSpecified = true;

        request.Web.Options = new WebSearchOption[]

        {

            WebSearchOption.DisableHostCollapsing,

            WebSearchOption.DisableQueryAlterations

        };

     

        return request;

    }

    Again, the code shown by the BuildRequest() method is autodescriptive. Just a precision about the search query : the code here assumes that you’re passing a keyword to the page via the querystring and in order to restrict the search to a particular website, your query must have the following form :

    keywordToSearchFor (site:http://www.thesitetosearch.com)

    3. Displaying the results

    private void DisplayResponse(SearchResponse response)

    {

        // If no results were found, display message and return

        if (response.Web == null || response.Web.Results == null)

        {

            this.litInformationZone.Text = "No results found.";

            return;

        }

     

        // Otherwise, perform databinding

        this.lvwSearchResults.DataSource = response.Web.Results;

        this.lvwSearchResults.DataBind();

    }

    As a crash occured when I submitted to Bing a request having no result (response.Web.Results having a NULL value), the first thing I do here is to protect the code from that error and warn the user by a message that her search query has no result. The litInformationZone is just a simple Literal object (and thus why I prefixed this “lit”). If the search has results, we perform the databinding with our ListView.

    4. Displaying the errors

    As errors may always occur, we have to handle them properly and display them to the user in a more convenient form than a disgracious exception message. Another lesson that Steve Krug teaches us in his Don’t make me think book is always apologize for the inconvenience to the user and explain to her briefly the error she’s encountered. This is where I started creating my own ErrorPanel UserControl that I used here and can also be reused later, so I suggest you doing the same. This UserControl is reffered in my code as pnlError and has one public property : ErrorMessage.

    private void DisplayErrors(XmlNode errorDetails)

    {

        // Add the default namespace to the namespace manager.

        XmlNamespaceManager nsmgr = new XmlNamespaceManager(errorDetails.OwnerDocument.NameTable);

        nsmgr.AddNamespace("api", "http://schemas.microsoft.com/LiveSearch/2008/03/Search");

        XmlNodeList errors = errorDetails.SelectNodes("./api:Errors/api:Error", nsmgr);

     

        if (errors != null)

        {

            StringBuilder builder = new StringBuilder();

     

            foreach (XmlNode error in errors)

            {

                foreach (XmlNode detail in error.ChildNodes)

                    builder.AppendLine(detail.Name + ": " + detail.InnerText);

     

                builder.AppendLine(Environment.NewLine);

            }

     

            this.pnlError.ErrorMessage = builder.ToString();

            this.pnlError.Visible = true;

        }

    }

    5. Enjoying the final result

    Time to watch some screens about the final result of all this work :

    Search results

    You can see from this picture the paging feature (that we’ll cover more in detail in a future article) and the highlight of the search keywords in the description text. By the way, this is accomplished by replacing the delimiter characters by a span having a specific CSS class. Code to accomplish this is shown below :

    if (HighlightText)

        description = description.Replace("\uE000", "<span class=’highlight’>").Replace("\uE001", "</span>");

    else

        description = description.Replace("\uE000", string.Empty).Replace("\uE001", string.Empty);

    Of course, your website needs to be indexed by Bing in order to perform searches on it. To check if your website is indexed, type “site:yoursiteurl” into Bing (ex : site:http://thibautvs.com). If it isn’t indexed yet, it will propose you to submit the URL so it can index it.

    6. Conclusion

    And this is it ! As you can see, the Bing API is pretty cool and easy to implement (actually, I took me less than 2 hours to get a first, beta running version). And a lot more services such as searching for images, videos, instant answers, mobile web, ads, phone books, using spell checkers or translations, … are also available (more info on the MSDN). Hope you’ve enjoyed this article, don’t hesitate if you would have any questions about that.

    See you ;)

    Share/Save/Bookmark

  • Implementing the Bing API in a ASP.NET website (part 1)

    Posted on July 21st, 2009 Thibaut 11 comments

    Bing

    Foreword : as the title suggests, the Bing API was implemented here in a ASP.NET website, but as the code dealing with the API is in C#, it should be straightforward to adapt it in some other .NET projects such as Silverlight. Hope you’ll enjoy this article !

    1. Context

    On the ASP.NET website I’m currently working on, I wanted to implement a search functionality as that’s the kind of very important criterias for the users on today’s websites. Steve Krug actually lists the search engine in the top 5 needed functionalities in his Don’t make me think book. I had several possibilities to do this :

    • Use the Google API, which is the first solution I’ve thought about
    • Use Yahoo & IBM’s OmniFind
    • Implement my own search engine
    • See what other options are available

    2. Choosing the right search engine API

    Of course, I wanted a totally free solution. I don’t want to have to pay each month or year for the kind of functionality I expect being free. So as I said, I thought about using Google API at first. There’s a free version but with advertisements. You’ve got to pay about 100$ a year if you want them out. Ok we can already eliminate this one. One doesn’t really wants ads of his direct concurrents to appear next to the search results on her own website.

    I also listed the solution of developing a little search engine by myself. Although I completely agree that this kind of project could be very interesting, I needed a fast solution and why developing something that I knew a way better version would be available for free out there on the web. There was also the OmniFind option, but the installation, deployment and database configuration makes it heavier to use than a simple API. At this moment, I thought about Bing. I tested it at its release and was very impressed by the relevance of the results, especially by the image search. And they’ve got all what I need for free. Plenty of documentation on the MSDN about the API, in multiple programming languages including C# that I’m using. Perfect ! Let’s implement this !

    3. Implementing the Bing API

    3.1. Choosing the protocol

    The Bing API can be used with the 3 following protocols :

    • JSON
    • XML
    • SOAP

    So the first step is to decide which one you’ll gonna use. In our case, that is, working with the code behind in C#, the use of SOAP was according to me the preferred choice. Indeed, JSON is best used with Javascript and we’re working in C#, so we can eliminate this choice. Remains XML and SOAP. XML is nice but you don’t want to have your code filled with potentially long XPATH strings when you can work with strongly typed objects and accessing their properties. Also, we beneficiate from the intellisense support for every information we’ll want to access. (more info on the MSDN about these protocols). Let’s now see how to implement the API using SOAP.

    3.2. Obtaining a Bing AppID

    In order to gain acccess to Bing through the API, you must first obtain an AppID from the Bing Developer Center.

    Bing AppID Just click on the Create an AppID link to get one. You’ll have to fill in a little form, with information such as your company name, website and your country.

    3.3. Adding the Web Reference under Visual Studio

    Web Reference Then, in Visual Studio, right click on your web project and click on Add Web Reference from the context menu.

    Type the following in the textbox : http://api.bing.net/search.wsdl?AppID=YourAppId&Version=2.2 (replace your AppID in this url). Then you should get this :

    Method detectedYou can see that the Search method from the API was correctly found. You can still change the Web reference name, which is the one you’ll use in your code to reference the Bing service.

    3.4. Integration of the API into the code

    In the page(s) where you want to use the Bing API, first include the following using statement :

    using [YourProjectDefaultNamespace].[TheWebReferenceName];

    Ex :

    using sampleproject.net.bing.api;

    Then you can implement and adapt the code listed on the MSDN to your needs.

    4. Implementing the Bing API - Part 2

    When you’ll have a look at the code from the MSDN, you’ll see that some adaptations are necessary.

    1. First, there is little chance that you want to implement Bing as a console application.
    2. Second, you want to use it to search on a particular website and not the whole web.
    3. You may also wish to handle the different types of errors the best way possible.
    4. And maybe you would like to have some ASP.NET code illustrating the implementation.

    This is exactly what’s coming next, where we’ll have a look at my implementation of the API in a ASP.NET website. So be sure to check out the part 2.

    Coming soon…

    Share/Save/Bookmark

  • AJAX tête la première

    Posted on March 4th, 2009 Thibaut 2 comments
    Ajax tête la première Ajax tête la première, or the equivalent in english Ajax head first, introduces you to dynamic and asynchronous UI development. In this book, you will not only learn how Ajax works (XmlHttp, aynchronous requests, callbacks, …) but also how to make effective use of it into your webpages with DOM, JSON, XML, etc… Through multiple application examples, the authors let you put into practise the theory following an interesting incremental approach. Starting with a very basic application, you will add blocks that will transform it into a reactive and modern one, with security issues - such as Sql injection - kept in mind. Below the pros and cons of this book :

    Pros

    • Very clear and well explained book (head first collection reputation)
    • Iterative approach : introduces basic concepts, then new ones through refactoring of previous code examples
    • Originality of examples : surf shop, the chaos project, …
    • Interesting chapter about the Document Object Model (DOM)
    • Also deals with security issues (Sql injection, …)
    • Briefly introduces the main javascript libraries and frameworks, such as script.aculo.usprototype and dojo

    Cons

    • I found the beginning too long (in fact too easy)
    •  Some minor errors in the book, including technical ones

    Conclusion

    I really appreciated this reading, which I found very original and very instructive at the same time. Covered topics, including Ajax basics, Javascript, Xml, Json, Dom and security will give you a strong starting point to go further in Ajax development. A must have.

    Share/Save/Bookmark