Search code examples
uwpgoogle-custom-search

Google Custom Search API - UWP


I am currently working on an assignment for school. The task is to create a UWP app that searches the web using Google Custom Search API with a search bar and button click that displays the results in a gridview or listview. I've looked for tutorials on the topic but there is not much out there. What is out there deals with console apps.

I can make a simple UI and understand that there needs to be data binding between the XAML and the code behind. I can create a class. However, despite my best efforts I cant make the call to the API work correctly and display the results on the listview. I've hard coded some values but connect to live data next week. Can anyone provide any assistance?

namespace Group_Project
{
    /// <summary>
    /// An empty page that can be used on its own or navigated to within a Frame.
    /// </summary>
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {

            String searchCode = textBox.Text;
            if (searchCode == null)
                throw new Exception("Need information in search");

            XDocument webRtn = new XDocument
                        (new XDeclaration("1.0", "utf-8", "yes"),
                         new XElement("SearchResults",
                             new XElement("SearchResult",
                                 new XAttribute("webiste", "www.google.com"),
                                 new XAttribute("search", "google"))));

            //String URL = "https://cse.google.com/cse?cx=009160378465265913901:plwe5st7ukl" + searchResults + ".xml";

            //Necessary to make the call to the internet to get the data.

            HttpClient client = new HttpClient();



            //var serviceresponse = client.GetAsync(URL).Result;

            //Checks for a success status code (200)

            //var serviceresponse = 200;

            //if (serviceresponse.IsSuccessStatusCode)

            //{

            //Get the content from the response

            //var responseContent = serviceresponse.Content;

            //Get the content into a string – async – you are still potentially pulling data down

            //string responseString = responseContent.ReadAsStringAsync().Result;

            //You don’t need to do this if you are testing with a local file but you will if connecting to the data

            //source directly

            //XDocument doc = XDocument.Parse(responseString);

            //Uncomment if you are reading from a local file

            XDocument doc = webRtn;

            //Using LINQ navigate to the data – this code will vary based on the incoming data structure and what data

            //you want to get

            // See detail on this below
            var query =
                   from element in doc.Element("SearchResults").Elements("SearchResult")
                   where element.Attribute("search").Value == "google"
                   select element.Attribute("webiste").Value;
            //Debug only

            Debug.WriteLine(query);

            ListView lst = new ListView();
            foreach (var website in query)
            {
                lst.Items.Add(website);
            }
            ListView Website = new ListView();
            WebsiteView.Items.Add("www.google.com");
            WebsiteView.Items.Add("www.bing.com");
            WebsiteView.Items.Add("www.msn.com");
            WebsiteView.Items.Add("www.fox.com");
            WebsiteView.Items.Add("www.abc.com");
            WebsiteView.Items.Add("www.nbc.com");

        }

    }
}

Solution

  • I can't make the call to the API work correctly.

    First, you can refer to this document to create your engine ID and get your API key. When you connect the api, you need to pass the two values to it. Then follow here to perfect your api request. Then you can use HttpClient request to get the result of json string and convert the json string to your viewmodel. For example:

    public MainPage()
    {
        this.InitializeComponent();
        lists = new ObservableCollection<MyResultViewModel>();
    }
    
    public ObservableCollection<MyResultViewModel> lists { get; set; }
    const string mykey = your_api_key;
    const string engId = your_engine_ID;
    
    private async void Button_Click(object sender, RoutedEventArgs e)
    {
        string searchText = textBox.Text;
        HttpClient httpClient = new HttpClient();
        string baseUri = $"https://www.googleapis.com/customsearch/v1?key={mykey}&cx={engId}";
        Uri requestUri = new Uri(baseUri+"&q="+ searchText);
    
        HttpResponseMessage httpResponse = new HttpResponseMessage();
        string httpResponseBody = "";
    
        try
        {
            //Send the GET request
            httpResponse = await httpClient.GetAsync(requestUri);
            httpResponse.EnsureSuccessStatusCode();
            httpResponseBody = await httpResponse.Content.ReadAsStringAsync();
            JsonObject obj = JsonValue.Parse(httpResponseBody).GetObject();
            JsonArray items = obj.GetNamedArray("items");
            for (uint i = 0; i < items.Count; i++)
            {
                string title = items.GetObjectAt(i).GetNamedString("title");
                MyResultViewModel vm = new MyResultViewModel() { Title = title };
                lists.Add(vm);
            }
        }
        catch (Exception ex)
        {
            httpResponseBody = "Error: " + ex.HResult.ToString("X") + " Message: " + ex.Message;
        }
    }
    

    Display the results on the listview.

    .xaml:

    <ListView ItemsSource="{x:Bind lists,Mode=OneWay}">
        <ListView.ItemTemplate>
            <DataTemplate x:DataType="local:MyResultViewModel">
                <TextBlock Text="{x:Bind Title,Mode=OneWay}"></TextBlock>
    
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
    

    Update:

    Create a simple viewmodel to receive json data.

    public class MyResultViewModel 
    {
        public string Title;
    }