SamplesV1/ADFv2CustomActivitySample/Listall.cs (69 lines of code) (raw):

using Microsoft.WindowsAzure.Storage; using Microsoft.WindowsAzure.Storage.Blob; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; namespace V2CustomExeSample { class Listall { /// <summary> /// This sample executable is to demonstrate how custom DLL you wrote for the ADFv1 .NET Custom Activity /// can be rewritten to a custom executable file to be executed by ADFv2 Custom Activity. /// </summary> static void Main(string[] args) { Console.WriteLine("Start to execute custom activity V2"); // Parse activity and reference objects info from input files dynamic activity = JsonConvert.DeserializeObject(File.ReadAllText("activity.json")); dynamic linkedServices = JsonConvert.DeserializeObject(File.ReadAllText("linkedServices.json")); // Extract Connection String from LinkedService dynamic storageLinkedService = ((JArray)linkedServices).First(_ => "BatchStorageLinkedService".Equals(((dynamic)_).name.ToString())); string connectionString = storageLinkedService.properties.typeProperties.connectionString.value; // Extract InputFilePath & OutputFilePath from ExtendedProperties // In ADFv2, Input & Output Datasets are not required for Custom Activity. In this sample the folderName and // fileName properties are stored in ExtendedProperty of the Custom Activity like below. You are not required // to get the information from Datasets. //"extendedProperties": { // "InputFolderPath": "batchjobs/filestocheck", // "OutputFilePath": "batchjobs/filestocheck/outputfile.txt" // } string inputFolderPath = activity.typeProperties.extendedProperties.InputFolderPath; string outputFilePath = activity.typeProperties.extendedProperties.OutputFilePath; //V1 Logger is no longer required as your executable can directly write to STDOUT Console.WriteLine(string.Format("InputFilePath: {0}, OutputFilePath: {1}", inputFolderPath, outputFilePath)); // Extract Input & Output Dataset // If you would like to continue using Datasets, pass the Datasets in referenceObjects of the Custom Activity JSON payload like below: //"referenceObjects": { // "linkedServices": [ // { // "referenceName": "BatchStorageLinkedService", // "type": "LinkedServiceReference" // } // ], // "datasets": [ // { // "referenceName": "InputDataset", // "type": "DatasetReference" // }, // { // "referenceName": "OutputDataset", // "type": "DatasetReference" // } // ] // } // Then you can use following code to get the folder and file info instead: //dynamic datasets = JsonConvert.DeserializeObject(File.ReadAllText("datasets.json")); //dynamic inputDataset = ((JArray)datasets).First(_ => ((dynamic)_).name.ToString().StartsWith("InputDataset")); //dynamic outputDataset = ((JArray)datasets).First(_ => ((dynamic)_).name.ToString().StartsWith("OutputDataset")); //string inputFolderPath = inputDataset.properties.typeProperties.folderPath; //string outputFolderPath = outputDataset.properties.typeProperties.folderPath; //string outputFile = outputDataset.properties.typeProperties.fileName; //string outputFilePath = outputFolderPath + "/" + outputFile; //Once needed info is prepared, core business logic down below remains the same. string output = string.Empty; // for use later. // create storage client for input. Pass the connection string. CloudStorageAccount inputStorageAccount = CloudStorageAccount.Parse(connectionString); CloudBlobClient inputClient = inputStorageAccount.CreateCloudBlobClient(); // initialize the continuation token before using it in the do-while loop. BlobContinuationToken continuationToken = null; do { // get the list of input blobs from the input storage client object. BlobResultSegment blobList = inputClient.ListBlobsSegmented(inputFolderPath, true, BlobListingDetails.Metadata, null, continuationToken, null, null); // Calculate method returns the number of occurrences of // the search term (“Microsoft”) in each blob associated // with the data slice. definition of the method is shown in the next step. output = Calculate(blobList, inputFolderPath, ref continuationToken, "Microsoft"); } while (continuationToken != null); CloudStorageAccount outputStorageAccount = CloudStorageAccount.Parse(connectionString); // write the name of the file. Uri outputBlobUri = new Uri(outputStorageAccount.BlobEndpoint, outputFilePath); // log the output file name Console.WriteLine("output blob URI: {0}", outputBlobUri.ToString()); // create a blob and upload the output text. CloudBlockBlob outputBlob = new CloudBlockBlob(outputBlobUri, outputStorageAccount.Credentials); Console.WriteLine("Writing {0} to the output blob", output); outputBlob.UploadText(output); } public static string Calculate(BlobResultSegment Bresult, string folderPath, ref BlobContinuationToken token, string searchTerm) { string output = string.Empty; Console.WriteLine("number of blobs found: {0}", Bresult.Results.Count<IListBlobItem>()); foreach (IListBlobItem listBlobItem in Bresult.Results) { CloudBlockBlob inputBlob = listBlobItem as CloudBlockBlob; if ((inputBlob != null) && (inputBlob.Name.IndexOf("$$$.$$$") == -1)) { string blobText = inputBlob.DownloadText(Encoding.ASCII, null, null, null); Console.WriteLine("input blob text: {0}", blobText); string[] source = blobText.Split(new char[] { '.', '?', '!', ' ', ';', ':', ',' }, StringSplitOptions.RemoveEmptyEntries); var matchQuery = from word in source where word.ToLowerInvariant() == searchTerm.ToLowerInvariant() select word; int wordCount = matchQuery.Count(); output += string.Format("{0} occurrences(s) of the search term \"{1}\" were found in the file {2}.\r\n", wordCount, searchTerm, inputBlob.Name); } } return output; } } }