0

I have an API call using client.GetAsync(url) within a SSIS script task but for some reason its not waiting for response from API and jumping back to the entry point for the script task which is public void Main(). Done some reading and found out that it might result in a deadlock for some reason but tried all the variations I could find to get it to work but with no luck. Something else that I don't understand is the exact same code is running on a webpage and that works perfect and waits for response from the api and continuing the flow.

Script Task entry point

The response here for payload is: ID =5, Status = WaitingForActivation, Method = "{null}", Result = "{Not yet computed}"

Here if in debug mode and moving the process back to go through the process again I noticed there 2 threads one current executing and the old one with the response I was expecting on the first call but not too sure what this means.

public void Main() {
  // TODO: Add your code here
  try {
    PackageDetails packageInfo = new PackageDetails {
      PackageNumber = 1234567891, Env = "Development", UserName = "USER"
    };
    var payload = API.ListHeadByPackAsync(packageInfo);
    //var test = GetResponse();
    Dts.TaskResult = (int) ScriptResults.Success;
  } catch (Exception ex) {
    System.Console.Write(ex.Message);
    Dts.TaskResult = (int) ScriptResults.Failure;
  }
}

API Call

public static class API {
  public static async Task<PackageDetails> ListHeadByPackAsync(PackageDetails package) {
    PackageDetails packageInfo = new PackageDetails();
    try {
      using(var client = new ApiClient(requestUrl, authToken)) {
        var response = await client.GetAsync(); //-> not waiting for response
      }
    } catch (Exception err) {
      switch (err.Message) {
        //TODO:
      }

    }
    return packageInfo;
  }
}

Client

public class ApiClient: IDisposable {
  private readonly TimeSpan _timeout;
  private HttpClient _httpClient;
  private HttpClientHandler _httpClientHandler;
  private readonly string _baseUrl;
  private readonly string _credentials;
  //private const string MediaTypeXml = "application/csv";

  public ApiClient(string baseUrl, string authToken, TimeSpan ? timeout = null) {
    _baseUrl = baseUrl;
    _credentials = Base64Encode(authToken);
    _timeout = timeout ?? TimeSpan.FromSeconds(90);
  }
  public async Task < string > GetAsync() {
    EnsureHttpClientCreated();
    using(var response = await _httpClient.GetAsync(_baseUrl).ConfigureAwait(continueOnCapturedContext: false))
    //-> after executing above line it will go straight to public void Main(), dose not wait for response
    {
      response.EnsureSuccessStatusCode();
      return await response.Content.ReadAsStringAsync();
    }
  }
  public void Dispose() {
    _httpClientHandler?.Dispose();
    _httpClient?.Dispose();
  }
  private void CreateHttpClient() {
    _httpClientHandler = new HttpClientHandler {
      AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip
    };
    _httpClient = new HttpClient(_httpClientHandler, false) {
      Timeout = _timeout
    };
    if (!string.IsNullOrWhiteSpace(_baseUrl)) {
      _httpClient.BaseAddress = new Uri(_baseUrl);
    }
    _httpClient.DefaultRequestHeaders.Add("Authorization", "Basic" + " " + _credentials);
  }
  private void EnsureHttpClientCreated() {
    if (_httpClient == null) {
      //ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
      CreateHttpClient();
    }
  }
  public static string Base64Encode(string token) {
    var tokenBytes = System.Text.Encoding.UTF8.GetBytes(token);
    return System.Convert.ToBase64String(tokenBytes);
  }
}
QuickSilver
  • 730
  • 5
  • 28
  • 1
    SSIS uses a framework that does not have async available yet. Sorry. – KeithL Jul 14 '22 at 17:46
  • My guess is that if you remove them that it will work and wait where you want. However, I tend to use the lighter weight WebClient(). And if it really complex, I would move to a console app. – KeithL Jul 14 '22 at 17:52
  • I need an ssis package to schedule a job to run at certain times. Will that work? – QuickSilver Jul 14 '22 at 17:54
  • 1
    You can always use a cmd to run a console app (if on same server) or powershell to run it on another computer. This is inside a job (for scheduling purposes). A job will inherently wait for completion on the console app. – KeithL Jul 14 '22 at 17:55
  • You mean that I will be able to do a script to run a console app from a ssis package with a schedule job? – QuickSilver Jul 14 '22 at 17:57
  • I mean you can run the console app directly from the job without using SSIS. – KeithL Jul 14 '22 at 17:58
  • 1
    Other script task limitations include not being able to use Nuget packages. So if a SSIS package contains only a script task, I highly recommend using console app (with Core) and run it directly from the job on your "schedule" – KeithL Jul 14 '22 at 18:01
  • I guess to clarify further. Your step in the job is to use command prompt to call your console app. The step will wait for completion which is different than a "Process" you may be familiar with in .NET – KeithL Jul 14 '22 at 18:03
  • Thanks for the info I thought this will work as is using the same system.net.http didn’t realise that the script task doesn’t support async calls. In addition will need to loop through multiple csv file grab data and send it via api so I guess that can be added to the console app. I got one concern if something fails will you be able to see the reason like you would to with an ssis package if its only a job that triggers the console app. Will that mean I need to create some sort of logging for it? – QuickSilver Jul 14 '22 at 18:12
  • What about if you use something like this: `mRes=Task.Run(async () => await AsyncMethod(...).ConfigureAwait(false).Result;` Will this work? – QuickSilver Jul 15 '22 at 10:29
  • I don't think you will be able to add the namespace that Task is in either. – KeithL Jul 15 '22 at 14:46
  • You will get an error message that it failed from the console app, but obviously it isn't always as perfect of a message that you would get if you were in visual studio unless you log the catch message. – KeithL Jul 15 '22 at 14:47
  • Got it thanks for the help will be looking at alternative now. – QuickSilver Jul 15 '22 at 14:48

0 Answers0