5 Replies Latest reply: Jan 19, 2017 9:26 PM by David Maurice RSS

    Exporting an App using REST API in C# .NET

    David Maurice

      Hi everyone, we're setting up a small environment where I will be automating the transfer of Qlik Sense Apps to different engines on different servers. Using the APIs I've been able to Import, Publish and get a ticket for Exporting an app, but not been able to use the APIs to Export.

       

      I'm probably missing something obvious, but it's not clear to me with the Export call:

      https://help.qlik.com/en-US/sense-developer/3.1/Subsystems/RepositoryServiceAPI/Content/RepositoryServiceAPI/RepositoryServiceAPI-App-Export-App-Call-2.htm

       

      How do I deal with the body of the request returned? I've written the content directly to the file system, but it's not a proper app when opened, so I'm not sure if I have to remove headers, decompress, or even look on the file system on the server or somewhere else (as you have to specify your path) to get the file export working. It looks like the text returned is almost a Qlik Sense App (comparing it with the original).

       

      I've also got task triggering working in C# via this example (and got the other API calls working): Working with REST API to trigger reload tasks

      My code is:

       

       

      HttpWebRequest request = (HttpWebRequest)WebRequest.Create(strServerName + @":4242/qrs/download/app/" + strAppID + "/" + strRequestGUID + "/" + strFilename + "?xrfkey=" + xrfkey);
      request.Method = "GET";
      request.Accept = "application/vnd.qlik.sense.app";
      request.Headers.Add("X-Qlik-xrfkey", xrfkey);
      request.Headers.Add("id", strAppID);
      
      // Add the certificate to the request and provide the user to execute as
      request.ClientCertificates.Add(SenseCert);
      request.Headers.Add("X-Qlik-User", strUserStringForQlik);
      
      //Send the request
      using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
      {
       using (Stream stream = response.GetResponseStream())
       {
      
        //So at this point, we have a stream when put into raw text looks like  
        //  a Qlik Sense App, but is not a Qlik Sense app.  
        using (StreamWriter sw = new StreamWriter(strFilename, false, Encoding.UTF8))
        {
         StreamReader sr = new StreamReader(stream, Encoding.UTF8);
         //We write the data to a file here, but it won't load in Qlik Sense
         while (!sr.EndOfStream)
         {
          string strLinedata = sr.ReadLine();
          sw.WriteLine(strLinedata);
         }
        }
      
       }
      }
      
        • Re: Exporting an App using REST API in C# .NET
          praveena mundolimoole

          david.maurice You must subclass and override one or more functions.

           

          class MyWebClient : WebClient

              {

                  protected override WebRequest GetWebRequest(Uri address)

                  {

                      HttpWebRequest request = (HttpWebRequest)base.GetWebRequest(address);

                      request.ClientCertificates.Add(SenseCert);

                      return request;

                  }

              }

           

          Use MyWebClient as below to export app.

           

          using (var client = new MyWebClient())

                      {

                          client.DownloadFile(strServerName + @":4242/qrs/download/app/" + strAppID + "/" + strRequestGUID + "/" + strFilename + "?xrfkey=" + xrfkey, "app.qvf");

                         

                      }

            • Re: Exporting an App using REST API in C# .NET
              David Maurice

              That is my fault, I did not include the Certificate code in my example, (there is nothing proprietary in it so I should have).

               

                // locate the client certificate and accept it as trusted
                 X509Certificate2 SenseCert = new X509Certificate2(strCertificatePath, "", X509KeyStorageFlags.MachineKeySet);
                 ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
              

               

               

              and this certificate "SenseCert" is then passed in. It is the code I use for the other requests I make.

            • Re: Exporting an App using REST API in C# .NET
              David Maurice

              So after some more research, I have figured it out. TL;DR the data returned in the request is a byte stream, and should be written as a byte stream not as a string.

               

              I had thought of using a byte stream, but since I have never used one of those before I used the wrong code, and it didn't work, so I kept on trying with the streamwriter. The streamwriter writes strings, and hence when I looked at the file, the text parts looked like a proper .QVF, but nothing else did.

              Honestly I'm surprised there's no easier way of writing a byte stream in C#, but at least it works!

               

              Code assume previous setup has been done, insert this over the top of the response:


              //Send the request
              using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
              {
               using (Stream stream = response.GetResponseStream())
               {
                // Create the local file
                Stream localStream = File.Create(strFilename);
                int bytesProcessed = 0;
                // Allocate a 1k buffer
                byte[] buffer = new byte[1024];
                int bytesRead;
                // Simple do/while loop to read from stream until
                // no bytes are returned
                do
                {
                 // Read data (up to 1k) from the stream
                 bytesRead = stream.Read(buffer, 0, buffer.Length);
                 // Write the data to the local file
                 localStream.Write(buffer, 0, bytesRead);
                 // Increment total bytes processed
                 bytesProcessed += bytesRead;
                } while (bytesRead > 0);
               }
              }
              
              
              
              

               

              I guess it should have been obvious, but clearly the obvious takes weeks to figure out whilst other things are being done!

                • Re: Exporting an App using REST API in C# .NET
                  praveena mundolimoole

                  Easier way of writing a byte stream or downloading a file in C#, is as mentioned in my above answer using WebClient.


                  class MyWebClient : WebClient

                      {

                          protected override WebRequest GetWebRequest(Uri address)

                          {

                              HttpWebRequest request = (HttpWebRequest)base.GetWebRequest(address);

                              request.ClientCertificates.Add(SenseCert);

                              return request;

                          }

                      }

                   

                  Use MyWebClient as below to export app.

                   

                  using (var client = new MyWebClient())

                              {

                                  client.DownloadFile(strServerName + @":4242/qrs/download/app/" + strAppID + "/" + strRequestGUID + "/" + strFilename + "?xrfkey=" + xrfkey, "app.qvf");

                            

                              }