KeyNotFoundException in DynamicJson - rally

Using the create defect example from the .NET toolkit page here.
I get the following error when trying to use the DynamicJsonObject -
toCreate["Name"] 'toCreate["Name"]' threw an exception of type 'System.Collections.Generic.KeyNotFoundException' dynamic {System.Collections.Generic.KeyNotFoundException}
The code I am using is just as the example states:
DynamicJsonObject toCreate = new DynamicJsonObject();
toCreate["Name"] = "My Defect";
CreateResult createResult = restApi.Create(workspaceRef, "defect", toCreate);
Is this a problem on my end or is there a defect in the API?

Below is the full example that works. When we create a defect:
CreateResult createResult = restApi.Create(workspaceRef, "defect", myDefect);
and immediately try to print its FormattedID:
Console.WriteLine(myDefect["FormattedID"]);
the same System.Collections.Generic.KeyNotFoundException is generated. Is it possible you have something similar in your code?
On the other hand, if we create a defect, and then get by reference,we can print the FormattedID, and there is no KeyNotFoundException:
DynamicJsonObject d = restApi.GetByReference(createResult.Reference, "FormattedID");
Console.WriteLine(d["FormattedID"]);
Here is the code. I made some changes to the example. Delete requires workspace reference parameter.
Since in the end the defect is deleted, you may find it in the recycle bin.
namespace CreateDefectFromExample
{
class Program
{
static void Main(string[] args)
{
//Initialize the REST API
RallyRestApi restApi = new RallyRestApi("user#co.com", "TopSecret1984", "https://rally1.rallydev.com", "1.40");
String workspaceRef = "/workspace/111111111"; //use your workspace OID
//Create an item
DynamicJsonObject myDefect = new DynamicJsonObject();
myDefect["Name"] = "worst defect ever";
CreateResult createResult = restApi.Create(workspaceRef, "defect", myDefect);
//Console.WriteLine(myDefect["FormattedID"]); //this line causes System.Collections.Generic.KeyNotFoundException
DynamicJsonObject d = restApi.GetByReference(createResult.Reference, "FormattedID");
Console.WriteLine(d["FormattedID"]);
//Update the item DynamicJsonObject toUpdate = new DynamicJsonObject();
myDefect["Description"] = "This is my defect.";
OperationResult updateResult = restApi.Update(createResult.Reference, myDefect);
//Get the item
DynamicJsonObject item = restApi.GetByReference(createResult.Reference, "Name");
string name = item["Name"];
//Query for items
Request request = new Request("defect");
request.Fetch = new List<string>()
{
"Name",
"Description",
"FormattedID"
};
request.Query = new Query("Name", Query.Operator.Equals, "My Defect");
QueryResult queryResult = restApi.Query(request);
foreach (var result in queryResult.Results)
{
//Process item
string formattedID = result["FormattedID"];
}
//Delete the item
OperationResult deleteResult = restApi.Delete(workspaceRef, createResult.Reference);
}
}
}

Related

Create Defect in Rally using REST API and C#

I am trying to programatically create a defect in Rally using C#. Below is my code and errors i am getting is
Error in creating defect!!!
Cannot parse object reference from "Unspecified"
Code:
RallyRestApi restApi;
restApi = new RallyRestApi(webServiceVersion: "v2.0");
//after successful authentication...
String workspaceRef = "/workspace/12345";
String projectRef = "/project/78321";
DynamicJsonObject badDefect = new DynamicJsonObject();
newDefect["Name"] = "Defect " + DateTime.Now;
newDefect["Project"] = projectRef ;
newDefect["Environment"] = "test branch";
newDefect["c_DefectSourceNEW"] = "old";
newDefect["Severity"] = "minor";
newDefect["Release"] = "Unspecificed";
CreateResult createResult = restApi.Create("Defect", newDefect);
if (createResult.Success == true)
{
Console.WriteLine("Defect created Successfully!!!");
}
else
{
Console.WriteLine("Error in creating defect!!!");
}
foreach (string s in createResult.Errors)
{
Console.WriteLine(s);
}
Can some one suggest what i might be doing incorrectly and in general the correct way to sepcify "Release" value for a defect???
All object relationships in wsapi are represented by refs. So you just need to set the value as its ref rather than its name, much like you're already doing with workspace and project.
Thanks Kyle for inputs. Since the Release ID was mandatory i solved by below for Release Input:
Request reRequest = new Request("Release");
reRequest.Workspace = workspaceRef;
reRequest.Query = new Query("Project", Query.Operator.Equals, projectRef);
QueryResult queryResult = restApi.Query(reRequest);
string reprojectRef = null;
foreach (DynamicJsonObject result in queryResult.Results)
{
reprojectRef = result["_ref"];
Console.WriteLine(reprojectRef);
Console.WriteLine("Name: " + result["Name"]);
if (result["Name"] == "MyReleaseName")
{
newDefect["Release"] = result["_ref"];
}
}

Permissions error creating rally milestone when using API Key

I'm trying to create rally milestones from an external app using an API Key for credential authorization, but I get the warning "Not authorized to create: Milestone" whenever I run the following code:
DynamicJsonObject toCreate = new DynamicJsonObject();
toCreate["Name"] = "test";
CreateResult createResult = restApi.Create("milestone", toCreate);
I ran the same code with defects and other rally objects without any issues, and I am able to update existing milestones. However, I still can't figure out how to create new milestones.
Assuming that ApiKey belongs to a user that has write access to the intended workspace, this code using v3.0.1 of .NET toolkit creates a Milestone in a default project of that workspace:
class Program
{
static void Main(string[] args)
{
RallyRestApi restApi = new RallyRestApi(webServiceVersion: "v2.0");
String apiKey = "_abc123";
restApi.Authenticate(apiKey, "https://rally1.rallydev.com", allowSSO: false);
String workspaceRef = "/workspace/1234";
try
{
DynamicJsonObject m = new DynamicJsonObject();
m["Name"] = "some milestone";
CreateResult result = restApi.Create(workspaceRef, "Milestone",m);
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
}
UPDATE:
The issue can be related to the request's scope. See how this error is replicated and resolved using a browser rest client here.
An equivalent C# code:
class Program
{
static void Main(string[] args)
{
RallyRestApi restApi = new RallyRestApi(webServiceVersion: "v2.0");
String apiKey = "_abc123";
restApi.Authenticate(apiKey, "https://rally1.rallydev.com", allowSSO: false);
String projectRef = "/project/2222";
String workspaceRef = "/workspace/1111";
try
{
DynamicJsonObject m = new DynamicJsonObject();
m["Name"] = "some milestone xxxt";
m["TargetProject"] = projectRef;
CreateResult result = restApi.Create(workspaceRef, "Milestone",m);
m = restApi.GetByReference(result.Reference, "FormattedID");
Console.WriteLine(m["FormattedID"]);
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
}

Trying to create defect using Rally .net REST API and unable to set Owner

Below is the piece of code I have tried, I am able to set Project value but not owner.
var restAPI = new RallyRestApi("abc#xyz.com", "1234");
String workspaceRef = "/workspace/12345678901";
String projectRef = "/project/9876543210";
DynamicJsonObject toCreate = new DynamicJsonObject();
//Pass Project
toCreate["Project"] = projectRef;
//Pass Owner
DynamicJsonObject myUser = restAPI.GetCurrentUser();
string myUserRef = myUser["_ref"];
toCreate["Owner"] = myUserRef;
CreateResult createResult = restAPI.Create(workspaceRef, "defect", toCreate);
Alternately I have tried below to set Owner, even this did not work for me.
String userRef = "/user/11123456225";
toCreate["Owner"] = userRef;
Any help would be appreciated.
I just tested this code that sets owner on a defect successfully:
{
RallyRestApi restApi = new RallyRestApi("user#co.com", "secret", "https://rally1.rallydev.com", "v2.0");
String workspaceRef = "/workspace/11111"; //use valid workspace OID in your Rally
String projectRef = "/project/12345"; //use valid project OID in your Rally
String userRef = "/user/777";
DynamicJsonObject d = new DynamicJsonObject();
d["Name"] = "some bug";
d["Project"] = projectRef;
d["Owner"] = userRef;
CreateResult createResult = restApi.Create(workspaceRef, "Defect", d);
DynamicJsonObject defect = restApi.GetByReference(createResult.Reference, "FormattedID");
Console.WriteLine(defect["FormattedID"]);
//update defect
defect["Description"] = "bad bug";
OperationResult updateResult = restApi.Update(defect["_ref"], defect);
}
What does "unable to set" mean: do you get an error message, or it fails silently while setting other fields?

Rally Rest API .NET Toolkit Creating Defect/User Story with Tags

I'm having some trouble creating a new defect or user story with a tag included. I've tried a few different ways, and typically the defect is created in Rally, but with no tags attached. From looking at the Rally API and the source code for the toolkit, it seems like the tags should be in an ArrayList. Here is my latest attempt. If anyone can point me in the right direction, I would appreciate it.
DynamicJsonObject itemToCreate = new DynamicJsonObject();
itemToCreate["project"] = project["_ref"];
ArrayList tagList = new ArrayList();
DynamicJsonObject myTag = new DynamicJsonObject();
myTag["_ref"] = "/tag/1435887928";
tagList.Add(myTag);
itemToCreate["Tags"] = tagList;
CreateResult itemToCreateResult = restApi.Create(workspace["_ref"], "defect", itemToCreate);
You are almost there:
ArrayList tagList = new ArrayList();
DynamicJsonObject myTag = new DynamicJsonObject();
myTag["_ref"] = "/tag/2222";
tagList.Add(myTag);
myStory["Tags"] = tagList;
updateResult = restApi.Update(createResult.Reference, myStory);
This code creates a user story, finds a tag based on ref and adds a tag to a story:
using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;
using Rally.RestApi;
using Rally.RestApi.Response;
namespace Rest_v2._0_test
{
class Program
{
static void Main(string[] args)
{
//Initialize the REST API
RallyRestApi restApi;
restApi = new RallyRestApi("user#co.com", "secret", "https://rally1.rallydev.com", "v2.0");
//Set our Workspace and Project scopings
String workspaceRef = "/workspace/11111"; //replace this OID with an OID of your workspace
//Create an item
DynamicJsonObject myStory = new DynamicJsonObject();
myStory["Name"] = "abcdefg11";
CreateResult createResult = restApi.Create(workspaceRef, "HierarchicalRequirement", myStory);
DynamicJsonObject s = restApi.GetByReference(createResult.Reference, "FormattedID");
Console.WriteLine(s["FormattedID"]);
myStory["Description"] = "This is my story.";
OperationResult updateResult = restApi.Update(createResult.Reference, myStory);
ArrayList tagList = new ArrayList();
DynamicJsonObject myTag = new DynamicJsonObject();
myTag["_ref"] = "/tag/2222";
tagList.Add(myTag);
//Update the item
myStory["Tags"] = tagList;
updateResult = restApi.Update(createResult.Reference, myStory);
}
}
}

how can I query for releases / iterations via rally c# api?

I am trying to query on both Release and Iteration so I can fill out a drop down list with these various values. I'm not quite sure how to do this, however. What are the members of the object that come back via the query if we are able to do this? (Name, FormattedID, CreationDate, etc). Do we just create a new request of type "Release" and "Iteration" ?
Thanks!
Here is a code that queries on releases based on a project reference. If this project is not in a default workspace of the user that runs the code we either need to hardcode the workspace reference or get it from the project.
class Program
{
static void Main(string[] args)
{
RallyRestApi restApi;
restApi = new RallyRestApi("user#co.com", "TopSecret1984", "https://rally1.rallydev.com", "1.40");
var projectRef = "/project/22222222"; //use your project OID
DynamicJsonObject itemWorkspace = restApi.GetByReference(projectRef, "Workspace");
var workspaceRef = itemWorkspace["Workspace"]["_ref"];
Dictionary<string, string> result = new Dictionary<string, string>();
try
{
Request request = new Request("Release");
request.ProjectScopeDown = false;
request.ProjectScopeUp = false;
request.Workspace = workspaceRef;
request.Fetch = new List<string>()
{
"Name"
};
// request.Query = new Query("Project.ObjectID", Query.Operator.Equals, "22222222"); //also works
request.Query = new Query("Project", Query.Operator.Equals, projectRef);
QueryResult queryResult = restApi.Query(request);
foreach (var r in queryResult.Results)
{
Console.WriteLine("Name: " + r["Name"]);
}
}
catch
{
Console.WriteLine("problem!");
}
}
}
}