RevisionHistory and Revisions

本小妞迷上赌 提交于 2019-12-07 13:32:51

问题


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??


回答1:


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]);
                }
            }
        }
    }



回答2:


I'm not sure you can do this using SOAP. The fetchFullObjects parameter does not populate sub object fields like Revision History and Revisions. These fields are available via WSAPI in one request however by specifying them in the fetch parameter.

In this case you'll probably have to do a service.read(rev) to populate the Revisions.




回答3:


I'm not sure what you're trying to do with the revision history, but another option you might want to look at is the new Lookback API:

https://rally1.rallydev.com/analytics/doc/

This gives a REST API with much a richer and parsable view of the history of artifacts. For example, to find the complete history for the stories under the project with ObjectID 1234 (or any sub-projects), you could do:

find={ _ProjectHierarchy: 1234, _TypeHierarchy: "HierarchicalRequirement" }

For the analytics team, the full URL would be:

https://rally1.rallydev.com/analytics/v2.0/service/rally/workspace/41529001/artifact/snapshot/query.js?find={_ProjectHierarchy:279050021,_TypeHierarchy:"HierarchicalRequirement"}

where 41529001 is the ObjectID of the workspace and 279050021 is the project OID.

You add the fields parameter to specify the fields you want back, or fields=true when you're in development mode to figure out what's available:

https://rally1.rallydev.com/analytics/v2.0/service/rally/workspace/41529001/artifact/snapshot/query.js?find={_ProjectHierarchy:279050021,_TypeHierarchy:%22HierarchicalRequirement%22}&fields=true

Note that fields=true is limited to 200 results per page though, so you should specify the actual list of fields you want in production. For example, to return the ObjectID, Story Name and dates the snapshots were created, it would become:

https://rally1.rallydev.com/analytics/v2.0/service/rally/workspace/41529001/artifact/snapshot/query.js?find={_ProjectHierarchy:279050021,_TypeHierarchy:%22HierarchicalRequirement%22}&fields=[%22ObjectID%22,%20%22Name%22,%20%22_ValidFrom%22,%20%22_ValidTo%22]

Another feature that may be of interest from this snapshot model is the _PreviousValues field, which holds the old values of the fields that changed in the current snapshot, so you can detect (and query for) changes in an artifact's state. More info here: https://rally1.rallydev.com/analytics/doc/Analytics2.0LookbackAPIUserManual.html?_debugResources=y&n=1364482493883#h.uv4o9mhshx4

Hope this helps.




回答4:


Here is a way to get and show revision history with REST.

import com.google.gson.JsonObject;
import com.rallydev.rest.RallyRestApi;
import com.rallydev.rest.request.QueryRequest;
import com.rallydev.rest.response.QueryResponse;
import com.rallydev.rest.util.Fetch;
import com.rallydev.rest.util.QueryFilter;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Comparator;
import java.util.HashMap;
import java.util.TreeSet;

public class revisions {

    public static void main(String[] args) throws URISyntaxException, IOException {

        // Configure RallyRestApi
        final String rallyURL = "https://rally1.rallydev.com";
        final String wsapiVersion = "v2.0";
        final RallyRestApi restApi = new RallyRestApi(new URI(rallyURL), "RallyID", "password");    // TODO: update id / password
        restApi.setWsapiVersion(wsapiVersion);

        // Select and query project information
        final String myProject = "A Project Name";                      // TODO: update project name
        QueryRequest projectRequest = new QueryRequest("Project");
        projectRequest.setFetch(new Fetch("Name", "Iterations"));
        projectRequest.setQueryFilter(new QueryFilter("Name", "=", myProject));
        QueryResponse projectQueryResponse = restApi.query(projectRequest);
        String iterationListRef = projectQueryResponse.getResults().get(0).getAsJsonObject().get("Iterations").getAsJsonObject().get("_ref").toString().replaceAll("\"", "");
        iterationListRef = iterationListRef.substring(iterationListRef.indexOf("Project"));

        // Query and store iteration information
        QueryRequest iterationRequest = new QueryRequest(iterationListRef);
        QueryResponse iterationQueryResponse = restApi.query(iterationRequest);

        HashMap<String, String> iterations = new HashMap<String, String>();
        String iterationName = "", iterationStartDate="";
        int irc = iterationQueryResponse.getTotalResultCount();
        for (int iter = 0; iter < irc; iter++) {
            JsonObject iterationObj = iterationQueryResponse.getResults().get(iter).getAsJsonObject();

            iterationName = iterationObj.get("_refObjectName").toString();
            iterationName = iterationName.substring(1, iterationName.length()-1);
            iterationStartDate = iterationObj.get("StartDate").toString().replaceAll("\"", "").substring(0, 10);
            iterations.put(iterationName, iterationStartDate);
        }

        // Query and store story information
        QueryRequest storyRequest = new QueryRequest("HierarchicalRequirement");
        String ir = iterationRequest.toUrl();
        storyRequest.setProject(ir.substring(0, ir.indexOf("/iterations")));
        QueryResponse storyQueryResponse = restApi.query(storyRequest);

        TreeSet<StoryInfo> stories = new TreeSet<StoryInfo>(new StoryComp());
        String refIteration = "", storyID = "", storyName = "", revHistory = "";
        int src = storyQueryResponse.getTotalResultCount();
        for (int story = 0; story < src; story++) {         
            JsonObject storyOjb = storyQueryResponse.getResults().get(story).getAsJsonObject();

            refIteration = storyOjb.get("Iteration").toString();
            if (refIteration.contains("_refObjectName")) 
                refIteration = storyOjb.get("Iteration").getAsJsonObject().get("_refObjectName").toString().replaceAll("\"", "");

            storyID = storyOjb.get("FormattedID").toString();
            storyID = storyID.substring(1, storyID.length()-1);

            storyName = storyOjb.get("_refObjectName").toString().replaceAll("\"", "");

        revHistory = storyOjb.get("RevisionHistory").getAsJsonObject().get("_ref").toString().replaceAll("\"", "");
        revHistory = revHistory.substring(revHistory.indexOf("revisionhistory"))+"/Revisions";

        stories.add(new StoryInfo(refIteration, ""+iterations.get(refIteration), storyID, storyName, revHistory));
        }

        System.out.println("Project: "+myProject);
        for (StoryInfo s:stories) {
            // Print the story iteration, id, name and revisions!
        System.out.println('\n'+s.iteration+" - "+s.id+" "+s.name);
        QueryRequest historyRequest = new QueryRequest(s.revHist);
        QueryResponse historyResponse = restApi.query(historyRequest);
        final int hrc = historyResponse.getTotalResultCount();
        for (int rev = 1; rev < hrc; rev++) {
            JsonObject historyObj = historyResponse.getResults().get(rev).getAsJsonObject();
//          System.out.println(historyObj);     // BINGO !!!
            System.out.println(historyObj.get("RevisionNumber")+" "+historyObj.get("CreationDate")+" "+historyObj.get("Description"));
        }                
        }
        restApi.close();
    }

    static class StoryComp implements Comparator<StoryInfo> {
        public int compare(StoryInfo i1, StoryInfo i2) {
            return (i1.startDate+i1.id).compareTo(i2.startDate+i2.id);
        }
    }   

    static class StoryInfo {
        String iteration, startDate, id, name, revHist;
        StoryInfo(String it, String sd, String i, String n, String rh) {
            iteration = it; startDate = sd; id = i; name = n; revHist = rh;
        }
    }

}


来源:https://stackoverflow.com/questions/15660664/revisionhistory-and-revisions

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!