title: In Dynamics CRM Plugin: How to force the code not to wait for async response
body: <p>So here is my scenario. I have to call an Azure Function through Dynamics CRM plugin code (C#) asynchronously, that is fine. But <strong>I don't want the code to wait for Azure Function's response</strong>. I just want to complete the code execution and exit.</p>
  
  <p>The Azure Function will take care of the updates back in the CRM if necessary.</p>
  
  <p>The reason why I don't want to wait is there is a 2 minutes time limit for plugin execution to complete in CRM Online. However, Azure Function could take several minutes to complete the process.</p>
  
  <p>Here is my plugin class code that is making a synchronous call to Azure Function. <em>(I can convert the call to async following <a href="https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/async/walkthrough-accessing-the-web-by-using-async-and-await" rel="nofollow noreferrer">this</a> document, but following that approach my code will still be waiting for the response).</em></p>
  
  <pre><code>public class CallAzureFunc : IPlugin
  {
      public void Execute(IServiceProvider serviceProvider)
      {
          // Extract the tracing service for use in debugging sandboxed plug-ins.  
          ITracingService tracer = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
  
          // Obtain the execution context from the service provider.  
          IPluginExecutionContext context = (IPluginExecutionContext) serviceProvider.GetService(typeof(IPluginExecutionContext));
  
          // The InputParameters collection contains all the data passed in the message request.  
          if (context.InputParameters.Contains("Target") &amp;&amp; context.InputParameters["Target"] is Entity)
          {
              // Obtain the target entity from the input parameters.  
              Entity entity = (Entity)context.InputParameters["Target"];
  
              // Verify that the target entity represents an entity type you are expecting.   
              if (entity.LogicalName != "account")
                  return;
  
              // Obtain the organization service reference which you will need web service calls.  
              IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
              IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);
  
              try
              {
                  // Plug-in business logic goes here.  
  
                  Data data = new Data
                  {
                      name = entity.Attributes["name"].ToString()
                  };
  
                  string result = CallFunction(tracer, data);
                  tracer.Trace($@"result: {result}");
              }
  
              catch (FaultException&lt;OrganizationServiceFault&gt; ex)
              {
                  throw new InvalidPluginExecutionException("An error occurred in MyPlug-in.", ex);
              }
  
              catch (Exception ex)
              {
                  tracer.Trace("MyPlugin: {0}", ex.ToString());
                  throw;
              }
          }
      }
  
      private string CallFunction(ITracingService tracer, Data data)
      {
          string json = JsonConvert.SerializeObject(data);
  
          string apiUrl = "https://&lt;AzureFunctionName&gt;.azurewebsites.net/api/";
          string token = "&lt;token&gt;";
          string content = null;
          string apiMethod = "CreateContactFromLead";
          string inputJson = json;
          string result = ApiHelper.ExecuteApiRequest(apiUrl, token, content, apiMethod, inputJson, tracer);
          return result;
      }
  }
  </code></pre>
  
  <p>And here are the helper methods to make an API call.</p>
  
  <pre><code>    internal static string ExecuteApiRequest(string apiUrl, string token, string content, string apiMethod, string inputJson, ITracingService tracer)
      {
          try
          {
              var data = Encoding.ASCII.GetBytes(inputJson);
  
              HttpWebRequest request = (HttpWebRequest)WebRequest.Create(String.Format(apiUrl + apiMethod));
              request.Method = "POST";
              request.ContentLength = inputJson.Length;
              request.ContentType = "application/json";
              request.ContentLength = data.Length;
              request.Headers.Add("x-functions-key", token);
              request.Accept = "application/json";
  
              // Send the data
              Stream newStream = request.GetRequestStream();
              newStream.Write(data, 0, data.Length);
              newStream.Close();
  
              // Get the resposne
              HttpWebResponse response = (HttpWebResponse)request.GetResponse();
  
              if (response != null)
              {
                  tracer.Trace("ApiHelper &gt; ExecuteApiRequest &gt; response.StatusCode: " + response.StatusCode);
                  tracer.Trace("ApiHelper &gt; ExecuteApiRequest &gt; response.StatusDescription: " + response.StatusDescription);
              }
  
              if (response.StatusCode == HttpStatusCode.OK || response.StatusDescription == "OK" || response.StatusDescription == "200")
              {
                  content = ReadStream(response, tracer);
              }
              else if (response.StatusCode == HttpStatusCode.NoContent || response.StatusDescription == "No Content" || response.StatusDescription == "204")
              {
                  content = null;
              }
              else
              {
                  if (response != null)
                  {
                      throw new Exception(String.Format("Status Code: {0}, Status Description: {1}",
                          response.StatusCode,
                          response.StatusDescription));
                  }
              }
  
              return content;
          }
          catch (Exception ex)
          {
              tracer.Trace("ApiHelper &gt; ExecuteApiRequest &gt; error: " + ex.Message);
              throw;
          }
      }
  
      private static string ReadStream(HttpWebResponse response, ITracingService tracer)
      {
          try
          {
              var responseJson = string.Empty;
              if (response != null)
              {
                  Stream dataStream = response.GetResponseStream();
                  if (dataStream != null)
                  {
                      using (StreamReader reader = new StreamReader(dataStream))
                      {
                          while (!reader.EndOfStream)
                          {
                              responseJson = reader.ReadToEnd();
                          }
                      }
                  }
              }
              return responseJson;
          }
          catch (Exception ex)
          {
              tracer.Trace("ApiHelper &gt; ReadStream &gt; error: " + ex.Message);
              throw ex;
          }
      }
  </code></pre>