2

So I'm writing a C#.NET application that will need to be able to read historical data from Rally. Specifically I need to retrieve the total Plan Estimate for a given release for each of the first 7 days of the Release.

I've read that there are basically two ways to do this; via the revision history or via the Lookback API and using POST. I figured the LBAPI would be cleaner and more robust so I went that path. Unfortunately, I've never worked with POST before so I'm not entirely sure what I'm doing.

Here's what I've come up with so far. I feel like I'm either close and missing something blindingly obvious, or I'm totally off:

string uri = @"https://rally1.rallydev.com/analytics/v2.0/service/rally/workspace/14457696030/artifact/snapshot/query.js";

DynamicJsonObject data = new DynamicJsonObject();
data["find"] = new DynamicJsonObject();
data["find"]["_ProjectHierarchy"] = 14457702297;
data["find"]["_TypeHierarchy"] = "HierarchicalRequirement";
data["find"]["Children"] = null;
data["find"]["__At"] = "2014-02-02T00Z%22";
data["fields"] = new string[] { "PlanEstimate", "ObjectID", "Name" };

DynamicJsonObject results = API.post(uri, data);

When I use the compiled url in a web browser, I get the right data back:

https://rally1.rallydev.com/analytics/v2.0/service/rally/workspace/14457696030/artifact/snapshot/query.js?find={%22_ProjectHierarchy%22:14457702297,%22_TypeHierarchy%22:%22HierarchicalRequirement%22,%22Children%22:null,%22__At%22:%222014-02-02T00Z%22}&fields=[%22ObjectID%22,%22Name%22,%22PlanEstimate%22]&start=0

When I use the C# code above and call:

DynamicJsonObject results = API.post(uri, data);

I get a WebException stating: "The remote server returned an error: (405) Method Not Allowed." which almost sounds like I can't even use that post method to begin with.

Any guidance would be greatly appreciated.

  • How do you connect to Rally? Do you have a proxy server? It's possible that the 405 response isn't coming from Rally, but from an upstream proxy instead. LBAPI supports either GET or POST. –  Apr 02 '14 at 05:23
  • Hey Mark, it's through my corporate network, which I'm assuming applies some sort of proxy? I'm looking now to see if IIS and Visual Studio are configured correctly. Is there a way for me to try using GET within the REST API? I only see a method for POST. Thanks. – Andrew McGrath Apr 02 '14 at 12:40
  • 1
    What is your API object in this instance? I was assuming it was a .NET WebClient. Note that the .NET REST DLL from Rally does not yet support Lookback API. –  Apr 02 '14 at 14:49
  • I was trying to use the .NET REST DLL. I assumed it was at least possible since the post method was accessible. In switching to using System.Net.WebRequest, and figuring out how to attach credentials, I was finally able to get it to work. Thanks for your help @MarkW – Andrew McGrath Apr 02 '14 at 16:48

1 Answers1

2

In case anyone else is looking to do something similar, this was my solution following Mark's guidance (Could probably be done cleaner, but this works for me):

    private static DynamicJsonObject getBaseline(string day, long projectID, long ReleaseID)
    {
        int pageSize = 200;
        string uri = @"https://rally1.rallydev.com/analytics/v2.0/service/rally/workspace/14457696030/artifact/snapshot/query.js?find={%22_ProjectHierarchy%22:" + 
                     projectID + @",%22_TypeHierarchy%22:%22HierarchicalRequirement%22,%22Release%22:{$in:[" + ReleaseID + @"]},%22Children%22:null,%22__At%22:%22" + 
                     day + @"T00Z%22}&fields=[%22PlanEstimate%22,%22ScheduleState%22]&hydrate=[%22ScheduleState%22]&start=0&pagesize=" + pageSize;

        DynamicJsonObject response = HttpGet(uri);
        DynamicJsonObject points = new DynamicJsonObject();

        foreach (var story in response["Results"])
        {
            // Do whatever
        }
        return points;
    }

    public static DynamicJsonObject HttpGet(string URI)
    {
        System.Net.WebRequest req = System.Net.WebRequest.Create(URI);
        req.Credentials = GetCredential();
        req.PreAuthenticate = true;
        req.ContentType = "application/json";
        System.Net.WebResponse resp = req.GetResponse();
        System.IO.StreamReader sr = new System.IO.StreamReader(resp.GetResponseStream());

        DynamicJsonObject result = new DynamicJsonSerializer().Deserialize(sr.ReadToEnd());
        // Not sure if all of these are necessary
        sr.Close(); sr.Dispose();
        resp.Close();
        sr.Close(); sr.Dispose();
        return result;
    }

    private static CredentialCache GetCredential()
    {
        if (credentialCache == null)
        {
            string url = @"https://rally1.rallydev.com/analytics/v2.0/service/rally/workspace/14457696030/artifact/snapshot/query.js?";
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;
            credentialCache = new CredentialCache();
            String user = ConfigurationManager.AppSettings["user"];
            String password = ConfigurationManager.AppSettings["password"];
            credentialCache.Add(new System.Uri(url), "Basic", new NetworkCredential(user, password));
        }
        return credentialCache;
    }