使用 ASP.NET 和 AJAX 1.0 消费 Windows Live Search Web 服务






4.50/5 (6投票s)
此应用程序会将 Windows Live Search Web 服务的搜索结果绑定到 GridView 控件,并利用 AJAX 1.0 进行搜索和分页。

引言
此应用程序会将 Windows Live Search Web 服务的搜索结果绑定到 GridView 控件,并利用 AJAX 1.0 进行搜索和分页。此应用程序允许您一次搜索多个网站。一个实际示例可以在 这里找到。然而,城市示例不像本文中的示例那样是 AJAX 驱动的。
您可以通过 web.config 文件自定义搜索属性。在继续之前,请确保满足以下要求。
- 已安装 ASP.NET 2.0。
- 在 IIS 中设置下载的应用程序,并选择 ASP.NET 2.0。
- 您的计算机上已安装 AJAX 1.0。
- 从 MS 获取用于此 Web 服务的密钥(MSN)。然后,您可以将密钥添加到 web.config 中的应用程序设置。
背景
我在网上找到了一些零散的示例,但都没有实质性的帮助。我认为这可能对那些希望看到工作示例的人有帮助。您总可以移除 AJAX,并通过查询字符串捕获搜索查询,只需进行一些小的更改。
使用代码
WindowsLiveSearch 类有一个名为 Search 的主要方法。实例化该类将在 web.config 中填充所需的属性,以便在 Search 方法中使用。
主要配置属性被组织为一个名为 LiveSearchProperties 的类型。
/// <summary>
/// Properties used for setting up web service
/// </summary>
public class LiveSearchProperties
{
    private string _searchLic;
    public string SearchLic
    {
        get { return _searchLic; }
        set { _searchLic = value; }
    }
    private int _resultsSize;
    public int ResultsSize
    {
        get { return _resultsSize; }
        set { _resultsSize = value; }
    }
    private string _searchSites;
    public string SearchSites
    {
        get { return _searchSites; }
        set { _searchSites = value; }
    }
    private SafeSearchOptions _searchOptions;
    public SafeSearchOptions SearchOptions
    {
        get { return _searchOptions; }
        set { _searchOptions = value; }
    }
}
在构造函数中,属性被填充。SP 是 WindowsLiveSearch 的本地属性,类型为 LiveSearchProperties。在此,配置设置存储在一个新的 LiveSearchProperties 实例中,然后存储在 SP(WindowsLiveSearch 属性)中。
/// <summary>
/// Creates a WindowsLiveSearch and fills properties with values
/// </summary>
public WindowsLiveSearch()
{
    // -------------------------------
    // Initialize properties
    // -------------------------------
    // Error Property
    ErrorMsg = "";
    // LiveSearchProperties
    LiveSearchProperties sp = new LiveSearchProperties();
    sp.SearchLic = ConfigurationManager.AppSettings["SearchLic"];
    sp.ResultsSize = Int32.Parse(ConfigurationManager.AppSettings["ResultsSize"]);
    sp.SearchSites = ConfigurationManager.AppSettings["SearchSites"];
    sp.SearchOptions = SafeSearchOptions.Off;
    SP = sp; // Save instance to class property
    sp = null; // Null out unused object
}
Search 方法如下所示:
/// <summary>  
/// This is the main function you call after object creation. 
/// You can pass the search query in here and get a list of 
/// results to work with. You can easily bind these results to an 
/// ASP.NET control if desired or foreach the list to get the data.
/// </summary>
/// <param name="searchQuery">The search query</param>
/// <returns>A generic list of search results</returns>
public IList<LiveSearchResults> Search(string searchQuery)
{
    // Basic checks
    if ((searchQuery == null) ||
        (searchQuery.Length == 0) ||
        (searchQuery.Trim() == ""))
        return null;
    IList<LiveSearchResults> resultsCollection = 
              new List<LiveSearchResults>();
    using (MSNSearchService s = new MSNSearchService())
    {
        SearchRequest searchRequest = new SearchRequest();
        searchRequest = SetUpRequest(searchRequest, searchQuery, SP);
        SearchResponse searchResponse;
        try
        {
            searchResponse = s.Search(searchRequest);
            resultsCollection = CaptureResults(searchResponse);
        }
        catch (Exception e)
        {
            ErrorMsg = e.ToString();
        }
        finally
        {
          // If there was an error
          if (ErrorMsg.Length > 0)
            LogMessage("There was an error with searchQuery: " +
              searchQuery);
          else
            LogMessage("A successful search was made with searchQuery: " +
              searchQuery);
        }
    }
    return resultsCollection;
}
Search 方法使用 MSNSearchService 类,该类利用两个主要类:SearchRequest 和 SearchResponse。SearchRequest 对象包含允许 Search 类理解您要进行的搜索类型的所有必需属性。在此示例中,我们将进行网络搜索。
以下是 SearchRequest 方法:
/// <summary>  
/// Sets up the MSN SearchRequest Object
/// </summary>
/// <param name="searchRequest">A SearchRequest Object</param>
/// <param name="searchQuery">The search query</param>
/// <param name="sp">LiveSearchProperties Object</param>
/// <returns>The SearchRequest Object</returns>
private SearchRequest SetUpRequest(
    SearchRequest searchRequest,
    string searchQuery,
    LiveSearchProperties sp)
{
   SourceRequest[] sr = new SourceRequest[1];
   sr[0] = new SourceRequest();
   sr[0].Source = SourceType.Web;
   sr[0].ResultFields = ResultFieldMask.All;
   sr[0].Count = sp.ResultsSize;
   sr[0].Offset = 0;
   searchRequest.Requests = sr;
   searchRequest.Query = searchQuery + " " + sp.SearchSites;
   searchRequest.SafeSearch = sp.SearchOptions;
   searchRequest.AppID = sp.SearchLic;
   searchRequest.Flags = SearchFlags.MarkQueryWords;
   searchRequest.CultureInfo = "en-US";
   return searchRequest;
}
设置请求后,您可以使用 Web 服务获取 SearchResponse。我创建了一个名为 CaptureResults 的方法来执行此操作。为了存储捕获的结果,我创建了一个名为 LiveSearchResults 的类型。
LiveSearchResults 属性
/// <summary>
/// Properties used to store search results
/// </summary>
public class LiveSearchResults
{
   private string _url;
   public string URL
   {
       get { return _url; }
       set { _url = value; }
   }
   private string _title;
   public string Title
   {
       get { return _title; }
       set { _title = value; }
   }
   private string _description;
   public string Description
   {
       get { return _description; }
       set { _description = value; }
   }
   private string _displayURL;
   public string DisplayURL
   {
       get { return _displayURL; }
       set { _displayURL = value; }
   }
   private string _cachedURL;
   public string CachedURL
   {
       get { return _cachedURL; }
       set { _cachedURL = value; }
   }
}
这是 CaptureResults 方法:
/// <summary>
/// Creates a list of Search Results
/// </summary>
/// <param name="search_Response">The LiveSearch Response</param>
/// <returns>A collection of search results</returns>
private IList<LiveSearchResults> CaptureResults(SearchResponse search_Response)
{
 // Create a collection object to build list
 IList<LiveSearchResults> resultsCollector = new List<LiveSearchResults>();
 //Get data from web service
 foreach (SourceResponse response in search_Response.Responses)
 {
   Result[] response_results = null;
   response_results = response.Results;
   //Secure and store output
   foreach (Result response_result in response_results)
   {
      LiveSearchResults row = new LiveSearchResults();
      row.URL = AntiXss.HtmlEncode(CheckForNull(response_result.Url));
      row.Title = AntiXss.HtmlEncode(CheckForNull(response_result.Title))
          .Replace("", "<strong>").Replace("", "</strong>");
      row.Description = AntiXss.HtmlEncode(CheckForNull(response_result.Description))
          .Replace("", "<strong>").Replace("", "</strong>");
      row.DisplayURL = AntiXss.HtmlEncode(CheckForNull(response_result.DisplayUrl))
          .Replace("", "<strong>").Replace("", "</strong>");
      row.CachedURL = AntiXss.HtmlEncode(CheckForNull(response_result.CacheUrl));
      resultsCollector.Add(row);
   }
 }
 return resultsCollector;
}
此方法使用 MS 的 AntiXssLibrary.dll。这将防止不需要的跨站点脚本数据存储在结果中。此方法生成一个通用列表并将其返回给 Search 方法,这将使您能够将结果绑定到 Web 控件。
表示层
ObjectDataSource 负责所有工作。
<asp:ObjectDataSource ID="ObjectDataSource1" runat="server" SelectMethod="Search"
 TypeName="Windows.Live.Search.WindowsLiveSearch" OnSelected="ObjectDataSource1_Selected">
 <SelectParameters>
   <asp:FormParameter FormField="searchBox" Name="searchQuery" Type="String" />
 </SelectParameters>
</asp:ObjectDataSource>
如所示,您可以看到我在 TypeName 参数中包含了该类。然后,我从类中选择了 "Search" 方法。
OnSelected 事件用于获取总结果数。考虑到 GridView 的 Count 属性仅给出屏幕上实际显示的结果数量,这是我所知的唯一方法。
OnSelected 方法
// Get the total number of records
protected void ObjectDataSource1_Selected(object sender, 
               ObjectDataSourceStatusEventArgs e)
{
  Instructionlbl.Text = "";
  try
  {
    IList<LiveSearchResults> resultsCollection = 
             new List<LiveSearchResults>();
    resultsCollection = (IList<LiveSearchResults>)e.ReturnValue;
    resultsTotal = resultsCollection.Count;
    if (resultsTotal == 0)
      Instructionlbl.Text = "Your search provided no results.";
  }
  catch (System.NullReferenceException)
  {
    Instructionlbl.Text = "Please enter a search term.";
  }
}
如果搜索查询为空,则会出现 System.NullReferenceException。因此,指令标签在此处用于要求用户“请输入搜索词”。
AJAX 相关内容
要使其工作,您必须将您希望更新的控件包含在 AJAX UpdatePanel 中。在此示例中,我将 GridView 控件和指令标签放入了 UpdatePanel 中。
要触发更新面板,只需提供以下内容:
<Triggers>
  <asp:AsyncPostBackTrigger ControlID="SearchButton" EventName="click" />
</Triggers>
这只是说明在发生 Click 事件时触发更新面板。
关注点
您需要的所有内容都将在项目下载中。您应该能够利用我的工作并根据您的需求进行自定义。您可以在 web.config 文件中尝试搜索设置。您还可以更改默认的搜索网站。所有设置都与使用 Live 搜索引擎进行高级搜索时使用的设置相同。
历史
- 11/13/2007
- 将项目添加到 Code Project。
- 11/20/2007
- 添加了日志记录(web.config 中的可选功能)
- 修复了字段空引用错误
- 添加了搜索
- 提供了“无结果”消息


