0

I am facing problem for download ing pdf file from api via c# code.I have already asked this questions in stackoverflow and I have get the answer from stackoverflow with below source code. This source code works fine only in visual Studio 2012 and above version. But I am using visual Studio 2010 with .Net framework 4.0 version. The below code is not working in visual Studio 2010 due compatibility issue (asynch and await keyword not supported). My question is what is the alternate source code for working in visual Studio 2010.

static string url = "https://einvoicing.internal.cleartax.co/v2/eInvoice/download?irns=7b46fb61d6e0883bdfdfb997ca25c4b5629d3062241532f6e8e6fcdfc0a95c9a";
static HttpClient client = new HttpClient(); 
static async Task DownloadCurrentAsync(string StrInvoiceNo)
    {

        client.DefaultRequestHeaders.Add("owner_id", "78c6beda-54a2-11ea-b064-0af3f8b02c24");
        client.DefaultRequestHeaders.Add("gstin", "29AAFCD5862R000");
        HttpResponseMessage response = await client.GetAsync(url);
        
        response.EnsureSuccessStatusCode(); // <= Will throw if unsuccessful
        using (FileStream fileStream = new FileStream(StrInvoiceNo.Replace("/","-") + ".pdf", FileMode.Create, FileAccess.Write, FileShare.None))
        {
            //copy the content from response to filestream
            await response.Content.CopyToAsync(fileStream);
            System.Diagnostics.Process.Start(StrInvoiceNo.Replace("/", "-") + ".pdf");
        }
    }
James Z
  • 12,209
  • 10
  • 24
  • 44
Materials
  • 7
  • 6
  • 3
    Any reason why you're still on VS 2010? – vc 74 Sep 20 '20 at 09:16
  • Actually we are 12 developers are using vs 2010 for the past 8 years. We are planning to upgrade latest version very soon. But it will take six month to upgrade – Materials Sep 20 '20 at 09:22
  • then it might be the correct time to start reading this kind of stuff [async-in-depth](https://learn.microsoft.com/en-us/dotnet/standard/async-in-depth) – Luuk Sep 20 '20 at 09:27
  • `using ( WebClient client = new WebClient() ) client.DownloadFile(url, destPath);` ? Also `DownloadFileAsync`, do you want that ? –  Sep 20 '20 at 09:31
  • Noted thanks, How to pass header information and how to use get method in webclient?? – Materials Sep 20 '20 at 09:34
  • Almost the same [question](https://stackoverflow.com/questions/63974586/async-not-working-with-visual-studio-2010-and-net-4-0) was asked already – Pavel Anikhouski Sep 20 '20 at 18:00

1 Answers1

3

You can use WebClient that is supported by Visual Studio 2010 (since .NET Framework 2.0):

using System.Net

using ( var client = new WebClient() )
{
  client.Headers.Add("owner_id", "78c6beda-54a2-11ea-b064-0af3f8b02c24");
  client.Headers.Add("gstin", "29AAFCD5862R000");
  client.DownloadFile(url, destPath);
}

There is also this supported method: DownloadFileAsync.

That you can use like that:

using System.Net
using System.ComponentModel;

using ( var client = new WebClient() )
{
  Exception ex = null;
  bool finished = false;
  client.Headers.Add("owner_id", "78c6beda-54a2-11ea-b064-0af3f8b02c24");
  client.Headers.Add("gstin", "29AAFCD5862R000");
  client.DownloadProgressChanged += progress;
  client.DownloadFileCompleted += completed;
  client.DownloadFileAsync(new Uri(url), destPath);
  while ( !finished )
  {
    Thread.Sleep(100);
    //Application.DoEvents();
  }
  if ( ex != null ) throw ex;
  // Do progress
  void progress(object sender, DownloadProgressChangedEventArgs e)
  {
    // 
  }
  // Download completed
  void completed(object sender, AsyncCompletedEventArgs e)
  {
    finished = true;
    if ( e.Error == null ) return;
    HttpStatusCode code = 0;
    WebExceptionStatus status = 0;
    if ( e.Error is WebException we )
    {
      status = we.Status;
      if ( we.Response is HttpWebResponse response )
        code = response.StatusCode;
    }
    ex = new WebException(e.Error.Message + Environment.NewLine + Environment.NewLine +
                          url + Environment.NewLine + Environment.NewLine +
                          status.ToString() + Environment.NewLine +
                          code.ToString());
  }
}

Instead of creating and throwing a new exception after error information extracted, as we can put to trash the e.Error exception, you can use a boolean and check it for the result and use a string message to show if needed.

At the top instead of Exception ex = null; :

bool isSuccess = true;

At the end instead of ex = new WebException(...) :

isSuccess = false;

string errorMessage = e.Error.Message + Environment.NewLine + Environment.NewLine +
                     url + Environment.NewLine + Environment.NewLine +
                     status.ToString() + Environment.NewLine +
                     code.ToString());

Hence instead of if ( ex != null ) throw ex; :

if ( !isSuccess ) ...

Also, I see that when we don't provide user info, the file is successfully downloaded but it is not a PDF, it is a text file, JSon it seems:

{"error_code":"102","error_message":"Invoice with the selected Input is not present in the Database","error_source":"CLEARTAX"}

So after download you can check if the file if a PDF (first line starting with some header like %PDF), or manage this result.

  • 2
    You should be careful of using `throw ex` as you'll lose the original stack trace, preventing you from seeing where the exception originally occurred. If you want to wrap in a custom exception, then you should pass the original exception as an inner exception, otherwise you should be using `throw`. – John H Sep 20 '20 at 09:44
  • 1
    @OlivierRogier It always applies, because otherwise you're teaching people that using `throw ex` is fine when for many cases that isn't true. Accurate stack traces should always be preserved - debugging is hard enough as it is. – John H Sep 20 '20 at 09:48
  • @JohnH Yes, this exception object instance is in the event args property. But it was not raised here. You can't try catch it... so the code I wrote. My code put to trash this useless exception, but indeed, you can use it as inner: `ex = new WebException(..., we)`. But `we`, as is, is really useless once `Status` and `StatusCode` extracted, but I could be wrong. Answer updated. –  Sep 20 '20 at 10:10
  • Sorry Olivier, I had to go do something. Thanks for the edits. – John H Sep 20 '20 at 10:54