RevisionHistory and Revisions
rally
Solution
To close the loop, here's an example showing how to do the service.read()'s that Kyle referred to. Mark's recommendation to use LBAPI will be a much more robust way to track artifact snapshots for sure, but you'll have to build the REST-query URL's to LBAPI on your own, Rally doesn't have a C# SDK for LBAPI (yet).
Just a heads-up, especially if you're just getting started with building your integration, I'd highly recommend using one of Rally's .NET REST SDK instead of SOAP.
REST is more robust, more performant, and, Webservices API 1.4x (x is yet-to-be-determined) will be the final API release to have SOAP support. Webservices 2.x will be REST-only, so using REST will be essential to anyone wanting new Webservices features moving forward.
namespace SOAP_QueryStoryRevisions
{
class Program
{
static void Main(string[] args)
{
// create a service object
RallyServiceService service = new RallyServiceService();
// Credentials
string rallyUser = "user@company.com";
string rallyPassword = "topsecret";
// set the service URL
service.Url = "https://rally1.rallydev.com/slm/webservice/1.37/RallyService";
// login to service using HTTP Basic auth
System.Net.NetworkCredential credential =
new System.Net.NetworkCredential(rallyUser, rallyPassword);
Uri uri = new Uri(service.Url);
System.Net.ICredentials credentials = credential.GetCredential(uri, "Basic");
service.Credentials = credentials;
service.PreAuthenticate = true;
// Configure the service to maintain an HTTP session cookie
service.CookieContainer = new System.Net.CookieContainer();
// Get current user
User user = (User)service.getCurrentUser();
// Get reference to UserProfile for current user
UserProfile profile = new UserProfile();
profile.@ref = user.UserProfile.@ref;
// Read will return a WSObject that you can then cast to a UserProfile
WSObject resultobj = service.read(profile);
UserProfile newprofile = (UserProfile)resultobj;
// Default workspace for current user
Console.WriteLine(newprofile.DefaultWorkspace.@ref);
// set workspace for query
Workspace workspace = new Workspace();
workspace.@ref = newprofile.DefaultWorkspace.@ref;
// Make the web service call
//---------------------------
// Look for Stories
string objectType = "hierarchicalrequirement";
// Find Stories
string queryString = "(FormattedID < US100)";
// Order by FormattedID Ascending
string orderString = "FormattedID asc";
// Fetch full objects, or return just object shells
// with the "@ref" attribute set. You can fetch the full version
// of a ref object later by calling service.read().
bool fetchFullObjects = true;
// Paging information
long start = 0;
long pageSize = 200;
// Query for project
QueryResult projectQueryResult = service.query(workspace, "Project", "(Name = \"My Project\")", orderString, fetchFullObjects, start, pageSize);
// look at the object returned from query()
Console.WriteLine("Query returned " + projectQueryResult.TotalResultCount + " Projects");
// Grab project
DomainObject myProjectObject = projectQueryResult.Results[0];
Project myProject = (Project)myProjectObject;
// issue query
QueryResult queryResult = service.query(workspace, myProject, true, true, objectType, queryString, orderString, fetchFullObjects, start, pageSize);
// look at the object returned from query()
Console.WriteLine("Query returned " + queryResult.TotalResultCount + " objects");
// loop through results returned
Console.WriteLine("There are " + queryResult.Results.Length + " objects on this page");
for (int i = 0; i < queryResult.Results.Length; i++)
{
// Results array is of type "DomainObject"
DomainObject rallyobject = queryResult.Results[i];
Console.WriteLine(" result[" + i + "] = " + rallyobject);
Console.WriteLine(" ref = " + rallyobject.@ref);
HierarchicalRequirement myStory = (HierarchicalRequirement)rallyobject;
Console.WriteLine("===> FormattedID = " + myStory.FormattedID);
Console.WriteLine("===> Story Name = " + myStory.Name);
RevisionHistory myStoryRevisionHistory = myStory.RevisionHistory;
// Perform service.read on RevisionHistory
RevisionHistory myRevisionHistoryHydrated = (RevisionHistory)service.read(myStoryRevisionHistory);
// Grab revisions
Revision[] myRevisions = myRevisionHistoryHydrated.Revisions;
// Loop through each Revision and read it, output summary
for (int j = 0; j < myRevisions.Length; j++)
{
Revision revisionHydrated = (Revision)service.read(myRevisions[j]);
Console.WriteLine("===> Revision[" + j + "] = " + revisionHydrated.RevisionNumber);
Console.WriteLine("===> Description: " + revisionHydrated.Description);
}
}
Console.ReadKey();
}
// determine if the result had errors
static bool hasErrors(OperationResult result)
{
return (result.Errors.Length > 0);
}
// print warnings and errors to the console
static void printWarningsErrors(OperationResult result)
{
if (result.Warnings.Length > 0)
{
Console.WriteLine("Result has warnings:");
for (int i = 0; i < result.Warnings.Length; i++)
{
Console.WriteLine(" warnings[" + i + "] = " + result.Warnings[i]);
}
}
if (result.Errors.Length > 0)
{
Console.WriteLine("Result has errors:");
for (int i = 0; i < result.Errors.Length; i++)
{
Console.WriteLine(" errors[" + i + "] = " + result.Errors[i]);
}
}
}
}
Problem
I am trying to get into the revision history, but I am unsure how to get to it. No matter what I do, it returns null. Relevant code is below: ``` string objectType = "HierarchicalRequirement"; string orderString = ""; bool fetchFullObjects = true; long start = 1; long pageSize = 200; QueryResult queryResult = Global.service.query(Global.workspace, objectType, queryString, orderString, fetchFullObjects, start, pageSize); int cnt = 0; for (int i = 0; i < queryResult.Results.Length; i++) { // Results array is of type "DomainObject" DomainObject rallyobject = queryResult.Results[i]; HierarchicalRequirement story = (HierarchicalRequirement)rallyobject; var rev = story.RevisionHistory; if (rev.Revisions != null) { // traverse revisions for info, never gets here } dataGridView3.Rows.Add(new object[] { story.FormattedID, story.Description, story.InProgressDate, story.AcceptedDate, story.PlanEstimate}); } // Return the avereage days from inprogress to accepted return; } ``` In debug, rev always comes back null.. Perhaps I am casting the query results incorrectly??