Access external web services

Plug-ins and custom workflow activities can access the network through the HTTP and HTTPS protocols. This capability provides support for accessing popular web services like social sites, news feeds, web services, and more. The following web access restrictions apply to this sandbox capability.

Other methods of accessing web services include the use of Webhooks and the Azure Service Bus. Refer to the links provided in the next sections for more information on those topics.

How to access external web services

Today most people are familiar with the System.Net.Http.HttpClient Class. HttpClient was introduced with .NET Framework 4.5 and provides significant capabilities over the System.Net.WebClient Class, which is now obsolete.

HttpClient is intended to be reused and is asynchronous by default. Because HttpClient is asynchronous by default, you need to break away from typical use patterns and add code to force the operations to be performed synchronously, typically by removing the await keyword and appending .GetAwaiter().GetResult() to any asynchronous calls.

public void Execute(IServiceProvider serviceProvider)
{
  //Extract the tracing service for use in plug-in debugging.
  ITracingService tracingService =
      (ITracingService)serviceProvider.GetService(typeof(ITracingService));

  try
  {
    tracingService.Trace("Downloading the target URI: " + webAddress);

    try
    {
      // Download the target URI using a Web client. Any .NET class that uses the
      // HTTP or HTTPS protocols and a DNS lookup should work.
      using (HttpClient client = new HttpClient())
      {
        client.Timeout = TimeSpan.FromMilliseconds(15000); //15 seconds
        client.DefaultRequestHeaders.ConnectionClose = true; //Set KeepAlive to false
        

        HttpResponseMessage response =  client.GetAsync(webAddress).Result; //Make sure it is synchonrous
        response.EnsureSuccessStatusCode();

        string responseText = response.Content.ReadAsStringAsync().Result; //Make sure it is synchonrous
        tracingService.Trace(responseText);
        //Log success in the Plugin Trace Log:
        tracingService.Trace("HttpClientPlugin completed successfully.");
      }
    }

    catch (AggregateException aex)
    {
      tracingService.Trace("Inner Exceptions:");

      foreach (Exception ex  in aex.InnerExceptions) {
        tracingService.Trace("  Exception: {0}", ex.ToString());
      }

      throw new InvalidPluginExecutionException(string.Format(CultureInfo.InvariantCulture,
          "An exception occurred while attempting to issue the request.", aex));
    }
  }
  catch (Exception e)
  {
    tracingService.Trace("Exception: {0}", e.ToString());
    throw;
  }
}

More information: Sample: Web access from a plug-in

Best practices

As called out in the following best practices articles:

You should make sure to set an appropriate Timeout period for your external calls and disable KeepAlive. See the previous links for more information.

See also

Plug-ins
Workflow extensions
Azure integration
Use Webhooks