ASP.net Web Api 2-Webservice durch SSIS-Paket aufrufen (Teil 3: SSIS-Skript-Task erstellen)
avatar

   Das Problem

Ausgehend vom Artikel2 dieser Serie wird in diesem Artikel der Code des Testclients in einen SSIS-Skript-Task umgebaut.

Die Lösung

Zunächst wird ein neues SSIS-Projekt erstellt, welches die beiden String-VariablenIds“ und „WsUrl“ erhält:
webapi-ssis-1

In einem Datenfluss-Task erstellen muss dann eine Skript-Komponente vom Typ „Microsoft Visual C# 2012“ erstellt werden.
Die beiden Variablen „Ids“ und „WsUrl“ werden als Readonly-Variablen zugreifbar gemacht:
webapi-ssis-2

Über den Reiter „Inputs and Outputs“ werden die nötigen Ausgabespalten erstellt:

  • Price         [DT_R8]
  • Name       [DT_STR]
  • Category  [DT_STR]
  • Id              [DT_I4]

webapi-ssis-3

Anschließend wird folgendes Skript eingefügt:

  1. #region Namespaces
  2. using System;
  3. using Microsoft.SqlServer.Dts.Pipeline.Wrapper;
  4. using SC_aecc13701db642ea9094a40822a7870a;
  5. using System.Text;
  6. using System.Net;
  7. using System.IO;
  8. using System.Web.Script.Serialization;
  9. #endregion
  10. [Microsoft.SqlServer.Dts.Pipeline.SSISScriptComponentEntryPointAttribute]
  11. public class ScriptMain : UserComponent
  12. {
  13.   public override void PreExecute()
  14.   {
  15.     base.PreExecute();
  16.   }
  17.   public override void PostExecute()
  18.   {
  19.     base.PostExecute();
  20.   }
  21.   public override void CreateNewOutputRows()
  22.   {
  23.     string webSrvUrl = Variables.WsUrl;
  24.     string postData = String.Format(„[{0}]“, Variables.Ids);
  25.     var result = GetWebServiceResult(webSrvUrl, postData);
  26.     foreach (var row in result)
  27.     {
  28.       Output0Buffer.AddRow();
  29.       Output0Buffer.Id = row.Id;
  30.       Output0Buffer.Name = row.Name;
  31.       Output0Buffer.Category = row.Category;
  32.       Output0Buffer.Price = row.Price;
  33.     }
  34.   }
  35.   private Product[] GetWebServiceResult(string webSrvUrl, string postData)
  36.   {
  37.     Product[] jsonResponse = null;
  38.     byte[] postBytes = Encoding.UTF8.GetBytes(postData);
  39.     // build web-request
  40.     WebRequest httpWReq = WebRequest.Create(webSrvUrl);
  41.     httpWReq.Credentials = CredentialCache.DefaultCredentials;
  42.     httpWReq.Method = WebRequestMethods.Http.Post;
  43.     httpWReq.ContentType = „application/json“;
  44.     httpWReq.ContentLength = postBytes.Length;
  45.     // build request-stream
  46.     using (Stream dataStream = httpWReq.GetRequestStream())
  47.     {
  48.       dataStream.Write(postBytes, 0, postBytes.Length);
  49.     }
  50.   // get response
  51.   try
  52.   {
  53.     HttpWebResponse httpWResp = (HttpWebResponse)httpWReq.GetResponse();
  54.     // if response successfully…
  55.     if (httpWResp.StatusCode == HttpStatusCode.OK)
  56.     {
  57.     // …get response-stream…
  58.     using (Stream responseStream = httpWResp.GetResponseStream())
  59.     {
  60.       string responseJson = String.Empty;
  61.     // …read streamReader…
  62.     using (StreamReader reader = new StreamReader  (responseStream))
  63.     {
  64.       responseJson = reader.ReadToEnd();
  65.        // … finally deserialize json (add reference System.Web.Extensions)
  66.       JavaScriptSerializer jsSr = new JavaScriptSerializer();
  67.       jsonResponse = jsSr.Deserialize<Product[]>(responseJson);
  68.       }
  69.     }
  70.   }
  71.   else
  72.   {
  73.     Fail(„Response not successfully!“);
  74.    }
  75.   }
  76.    catch (Exception ex)
  77.   {
  78.     Fail(„Exception: „ + ex.ToString());
  79.    }
  80.   return jsonResponse;
  81. }
  82.   private void Fail(string errorMessage)
  83.   {
  84.     bool fail = false;
  85.     IDTSComponentMetaData100 compMetaData = this.ComponentMetaData;
       compMetaData.FireError(1, „Error getting data from webservice“, errorMessage, „“, 0, out fail);
  86.   }
  87. }

Eine wesentliche Änderungen zum Test-Client findet sich in den in den Zeilen 27 und 28. Dort werden die Webservice-URL und die abzurufenden IDs aus den Readonly-Variablen bezogen.

Die Schleife ist weitgehend gleich geblieben, es wird in Zeile 33 lediglich eine neue Output-Zeile hinzugefügt und statt der Console.WriteLine()-Anweisungen werden die Results nun in die zuvor neu angelegte Output-Zeile eingefügt (Zeile 35 bis 38).

Die Fail-Methode gibt nun, statt eines Console-WriteLine() eine Fehlermeldung vom Typ IDTSComponentMetaData zurück.

Nachdem im Visual Studio Code-Editor einmal auf „Build“ geklickt wurde, kann der Editor geschlossen werden. Die Ausgabe das Skript-Tasks wird dann einem Sort-Task übergeben, welcher nach der ID-Spalte sortiert. Mittels eines Data-Viewers können die ausgegebenen Spalten des Skript-Tasks dann kontrolliert werden:webapi-ssis-4

Fazit

Wie bereits im vorherigen Artikel erwähnt gefällt es mir nicht den Webservice derat „low-level“ aufzurufen.
Da diese Drittanbieter-Komponenten in meinem Fall allerdings nicht verwendet werden sollten, war dies eine zielführende Lösung.
Die unter [1] verlinkte SSIS-Komponente werde ich mir in einem weiteren Blog-Post einmal genauer anschauen.

Links

[1] https://marketplace.visualstudio.com/items?itemName=ZappySys.SSISRESTAPIWebServiceTask

Schreibe einen Kommentar