Search code examples
c#.netrally

Downloading attachments from rally using C# and .NET


My ultimate goal in the script I am writing is to download all attachments from rally. I was able to successfully connect to the server, make a request for all attachments in a workspace, and finally, iterate through to retrieve the content of each attachment. This yields a dynamicJsonObject of the AttachmentContent. Being new to any API as well C# and .NET, I am now stuck. I cannot figure out a way to access and download the content of this object to a file on my computer. The line I have commented below is where I am currently getting an error and I am stuck. Any help would be greatly appreciated.

P.S. Here is my main method:

static void Main(string[] args)
    {
        RallyRestApi restApi = new RallyRestApi("[email protected]", "password", "https://rally1.rallydev.com", "1.43");
        Request request = new Request("attachment");
        request.Workspace = "/workspace/186282018";
        request.Fetch = new List<string>() { "Name", "Artifact", "Content", "ContentType" };
        request.Query = new Query("");
        QueryResult queryResult = restApi.Query(request);
        int count = 0;
        foreach (var result in queryResult.Results)
        {     
            DynamicJsonObject content = result["Content"];
            //var binContent = content["Content"];
            count++;
        }
        Console.WriteLine(count);
        Console.ReadLine();
    }

Solution

  • Here's an example that simply writes the content bytes to a File and skips the mime-type checking:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Drawing;
    using System.Drawing.Imaging;
    using System.IO;
    using Rally.RestApi;
    using Rally.RestApi.Response;
    
    namespace RestExample_DownloadAttachment
    {
        class Program
        {
            static void Main(string[] args)
            {
                 //Initialize the REST API
                RallyRestApi restApi;
    
                // Rally parameters
                String userName = "[email protected]";
                String userPassword = "topsecret";
                String rallyURL = "https://rally1.rallydev.com";
                String wsapiVersion = "1.43";
    
                restApi = new RallyRestApi(
                    userName,
                    userPassword,
                    rallyURL,
                    wsapiVersion
                );
    
    
                //Set our Workspace and Project scopings
                String workspaceRef = "/workspace/12345678910";
                String projectRef = "/project/12345678911";
                bool projectScopingUp = false;
                bool projectScopingDown = true;
    
                // Find User Story that we want to pull attachment from
    
                // Tee up Story Request
                Request storyRequest = new Request("hierarchicalrequirement");
                storyRequest.Workspace = workspaceRef;
                storyRequest.Project = projectRef;
                storyRequest.ProjectScopeDown = projectScopingDown;
                storyRequest.ProjectScopeUp = projectScopingUp;
    
                // Fields to Fetch
                storyRequest.Fetch = new List<string>()
                    {
                        "Name",
                        "FormattedID",
                        "Attachments"
                    };
    
                // Add a query
                storyRequest.Query = new Query("FormattedID", Query.Operator.Equals, "US163");
    
                // Query Rally for the Story
                QueryResult queryResult = restApi.Query(storyRequest);
    
                // Pull reference off of Story fetch
                DynamicJsonObject storyObject = queryResult.Results.First();
                String storyReference = storyObject["_ref"];
                Console.WriteLine("Looking for attachments off of Story: " + storyReference);
    
                // Grab the Attachments collection
                var storyAttachments = storyObject["Attachments"];
                // Let's download the first attachment for starters
                var myAttachmentFromStory = storyAttachments[0];
                // Pull the ref
                String myAttachmentRef = myAttachmentFromStory["_ref"];
                Console.WriteLine("Found Attachment: " + myAttachmentRef);
    
                // Fetch fields for the Attachment
                string[] attachmentFetch = { "ObjectID", "Name", "Content", "ContentType", "Size"};
    
                // Now query for the attachment
                DynamicJsonObject attachmentObject = restApi.GetByReference(myAttachmentRef, "true");
    
                // Grab the AttachmentContent
                DynamicJsonObject attachmentContentFromAttachment = attachmentObject["Content"];
                String attachmentContentRef = attachmentContentFromAttachment["_ref"];
    
                // Lastly pull the content
                // Fetch fields for the Attachment
                string[] attachmentContentFetch = { "ObjectID", "Content" };
    
                // Now query for the attachment
                Console.WriteLine("Querying for Content...");
                DynamicJsonObject attachmentContentObject = restApi.GetByReference(attachmentContentRef, "true");
                Console.WriteLine("AttachmentContent: " + attachmentObject["_ref"]);
    
                String base64EncodedContent = attachmentContentObject["Content"];
    
                // File information
                String attachmentSavePath = "C:\\Users\\username\\";
                String attachmentFileName = attachmentObject["Name"];
                String fullAttachmentFile = attachmentSavePath + attachmentFileName; 
    
                // Determine attachment Content mime-type
                String attachmentContentType = attachmentObject["ContentType"];
    
                try {
    
                    // Output base64 content to File
                    Console.WriteLine("Saving base64 AttachmentContent String to File.");
    
                    File.WriteAllBytes(@fullAttachmentFile, Convert.FromBase64String(base64EncodedContent));
                }
                catch (Exception e)
                {
                    Console.WriteLine("Unhandled exception occurred while writing file: " + e.StackTrace);
                    Console.WriteLine(e.Message);
                }
    
                Console.ReadKey();
            }
        }
    }