Quickstart: Get image insights using the Bing Visual Search REST API and C#

Warning

On October 30, 2020, the Bing Search APIs moved from Azure AI services to Bing Search Services. This documentation is provided for reference only. For updated documentation, see the Bing search API documentation. For instructions on creating new Azure resources for Bing search, see Create a Bing Search resource through the Azure Marketplace.

This quickstart demonstrates how to upload an image to the Bing Visual Search API and view the insights that it returns.

Prerequisites

Create an Azure resource

Start using the Bing Visual Search API by creating one of the following Azure resources:

Bing Search v7 resource

  • Available through the Azure portal until you delete the resource.
  • Select the S9 pricing tier.

Multi-service resource

  • Available through the Azure portal until you delete the resource.
  • Use the same key and endpoint for your applications, across multiple Azure AI services.

Create and initialize a project

  1. In Visual Studio, create a new console solution named BingSearchApisQuickStart. Add the following namespaces to the main code file:

    using System;
    using System.Text;
    using System.Net;
    using System.IO;
    using System.Collections.Generic;
    
  2. Add variables for your subscription key, endpoint, and path to the image you want to upload. For the uriBase value, you can use the global endpoint in the following code, or use the custom subdomain endpoint displayed in the Azure portal for your resource.

        const string accessKey = "<my_subscription_key>";
        const string uriBase = "https://api.cognitive.microsoft.com/bing/v7.0/images/visualsearch";
        static string imagePath = @"<path_to_image>";
    
  3. Create a method named GetImageFileName() to get the path for your image.

    static string GetImageFileName(string path)
            {
                return new FileInfo(path).Name;
            }
    
  4. Create a method to get the binary data of the image.

    static byte[] GetImageBinary(string path)
    {
        return File.ReadAllBytes(path);
    }
    

Build the form data

  1. To upload a local image, first build the form data to send to the API. The form data includes the Content-Disposition header, the name parameter set to "image", and the filename parameter set to the file name of the image. The contents of the form contain the binary data of the image. The maximum image size you can upload is 1 MB.

    --boundary_1234-abcd
    Content-Disposition: form-data; name="image"; filename="myimagefile.jpg"
    
    ÿØÿà JFIF ÖÆ68g-¤CWŸþ29ÌÄøÖ‘º«™æ±èuZiÀ)"óÓß°Î= ØJ9á+*G¦...
    
    --boundary_1234-abcd--
    
  2. Add boundary strings to format the POST form data. Boundary strings determine the start, end, and newline characters for the data.

    // Boundary strings for form data in body of POST.
    const string CRLF = "\r\n";
    static string BoundaryTemplate = "batch_{0}";
    static string StartBoundaryTemplate = "--{0}";
    static string EndBoundaryTemplate = "--{0}--";
    
  3. Use the following variables to add parameters to the form data:

    const string CONTENT_TYPE_HEADER_PARAMS = "multipart/form-data; boundary={0}";
    const string POST_BODY_DISPOSITION_HEADER = "Content-Disposition: form-data; name=\"image\"; filename=\"{0}\"" + CRLF +CRLF;
    
  4. Create a function named BuildFormDataStart() to create the start of the form data by using the boundary strings and image path.

        static string BuildFormDataStart(string boundary, string filename)
        {
            var startBoundary = string.Format(StartBoundaryTemplate, boundary);
    
            var requestBody = startBoundary + CRLF;
            requestBody += string.Format(POST_BODY_DISPOSITION_HEADER, filename);
    
            return requestBody;
        }
    
  5. Create a function named BuildFormDataEnd() to create the end of the form data by using the boundary strings.

        static string BuildFormDataEnd(string boundary)
        {
            return CRLF + CRLF + string.Format(EndBoundaryTemplate, boundary) + CRLF;
        }
    

Call the Bing Visual Search API

  1. Create a function to call the Bing Visual Search endpoint and return the JSON response. The function takes the start and end of the form data, a byte array containing the image data, and a contentType value.

  2. Use a WebRequest to store your URI, contentType value, and headers.

  3. Use request.GetRequestStream() to write your form and image data, and then get the response. Your function should be similar to the following code:

        static string BingImageSearch(string startFormData, string endFormData, byte[] image, string contentTypeValue)
        {
            WebRequest request = HttpWebRequest.Create(uriBase);
            request.ContentType = contentTypeValue;
            request.Headers["Ocp-Apim-Subscription-Key"] = accessKey;
            request.Method = "POST";
    
            // Writes the boundary and Content-Disposition header, then writes
            // the image binary, and finishes by writing the closing boundary.
            using (Stream requestStream = request.GetRequestStream())
            {
                StreamWriter writer = new StreamWriter(requestStream);
                writer.Write(startFormData);
                writer.Flush();
                requestStream.Write(image, 0, image.Length);
                writer.Write(endFormData);
                writer.Flush();
                writer.Close();
            }
    
            HttpWebResponse response = (HttpWebResponse)request.GetResponseAsync().Result;
            string json = new StreamReader(response.GetResponseStream()).ReadToEnd();
    
            return json;
        }
    

Create the Main method

  1. In the Main() method of your application, get the filename and binary data of your image.

    var filename = GetImageFileName(imagePath);
    var imageBinary = GetImageBinary(imagePath);
    
  2. Set up the POST body by formatting its boundary. Then, call BuildFormDataStart() and BuildFormDataEnd() to create the form data.

    // Set up POST body.
    var boundary = string.Format(BoundaryTemplate, Guid.NewGuid());
    var startFormData = BuildFormDataStart(boundary, filename);
    var endFormData = BuildFormDataEnd(boundary);
    
  3. Create the ContentType value by formatting CONTENT_TYPE_HEADER_PARAMS and the form data boundary.

    var contentTypeHdrValue = string.Format(CONTENT_TYPE_HEADER_PARAMS, boundary);
    
  4. Get the API response by calling BingImageSearch(), and then print the response.

    var json = BingImageSearch(startFormData, endFormData, imageBinary, contentTypeHdrValue);
    Console.WriteLine(json);
    Console.WriteLine("enter any key to continue");
    Console.readKey();
    

Using HttpClient

If you use HttpClient, you can use the MultipartFormDataContent class to build the form data. Use the following sections of code to replace the corresponding methods in the previous example:

  1. Replace the Main() method with the following code:

            static void Main()
            {
                try
                {
                    Console.OutputEncoding = System.Text.Encoding.UTF8;
    
                    if (accessKey.Length == 32)
                    {
                        if (IsImagePathSet(imagePath))
                        {
                            var filename = GetImageFileName(imagePath);
                            Console.WriteLine("Getting image insights for image: " + filename);
                            var imageBinary = GetImageBinary(imagePath);
    
                            var boundary = string.Format(BoundaryTemplate, Guid.NewGuid());
                            var json = BingImageSearch(imageBinary, boundary, uriBase, accessKey);
    
                            Console.WriteLine("\nJSON Response:\n");
                            Console.WriteLine(JsonPrettyPrint(json));
                        }
                    }
                    else
                    {
                        Console.WriteLine("Invalid Bing Visual Search API subscription key!");
                        Console.WriteLine("Please paste yours into the source code.");
                    }
    
                    Console.Write("\nPress Enter to exit ");
                    Console.ReadLine();
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.Message);
                }
            }
    
  2. Replace the BingImageSearch() method with the following code:

            /// <summary>
            /// Calls the Bing visual search endpoint and returns the JSON response.
            /// </summary>
            static string BingImageSearch(byte[] image, string boundary, string uri, string subscriptionKey)
            {
                var requestMessage = new HttpRequestMessage(HttpMethod.Post, uri);
                requestMessage.Headers.Add("Ocp-Apim-Subscription-Key", accessKey);
    
                var content = new MultipartFormDataContent(boundary);
                content.Add(new ByteArrayContent(image), "image", "myimage");
                requestMessage.Content = content;
    
                var httpClient = new HttpClient();
    
                Task<HttpResponseMessage> httpRequest = httpClient.SendAsync(requestMessage, HttpCompletionOption.ResponseContentRead, CancellationToken.None);
                HttpResponseMessage httpResponse = httpRequest.Result;
                HttpStatusCode statusCode = httpResponse.StatusCode;
                HttpContent responseContent = httpResponse.Content;
    
                string json = null;
    
                if (responseContent != null)
                {
                    Task<String> stringContentsTask = responseContent.ReadAsStringAsync();
                    json = stringContentsTask.Result;
                }
    
                return json;
            }
    

Next steps