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"];
}
}
Related
My ASP.NET Core MVC project has several reports. To render the reports as PDF, I'm using AspNetCore.Reporting library.
This library works fine for a single report but due to some cache issues it throws an exception while generating another report. The solution I found on the internet was to run report generation as a new process but I don't know how to implement that.
I found the suggestion to use Tmds.ExecFunction to run report generation as a seperate process. But I dont know how to pass parameters to the function.
Here is my code:
string ReportName = "invoiceDine";
DataTable dt = new DataTable();
dt = GetInvoiceItems(invoiceFromDb.Id);
Dictionary<string, string> param = new Dictionary<string, string>();
param.Add("bParam", $"{invoiceFromDb.Id}");
param.Add("gParam", $"{salesOrderFromDb.Guests}");
param.Add("tParam", $"{invoiceFromDb.Table.Table}");
param.Add("dParam", $"{invoiceFromDb.Time}");
param.Add("totalP", $"{invoiceFromDb.SubTotal}");
param.Add("t1", $"{tax1}");
param.Add("t2", $"{tax2}");
param.Add("tA1", $"{tax1Amount}");
param.Add("tA2", $"{tax2Amount}");
param.Add("AT1", $"{totalAmountWithTax1}");
param.Add("AT2", $"{totalAmountWithTax2}");
param.Add("terminalParam", $"{terminalFromDb.Name}");
param.Add("addressParam", $"{t.Address}");
param.Add("serviceParam", "Service Charges of applicable on table of " + $"{personForServiceCharges}" + " & Above");
var result = reportService.GenerateReport(ReportName, param, "dsInvoiceDine", dt);
return File(result,"application/Pdf");
This is my version of the function:
``` public byte[] GenerateReport(string ReportName, Dictionary<string,string> Parameters,string DataSetName,DataTable DataSource )
{
string guID = Guid.NewGuid().ToString().Replace("-", "");
string fileDirPath = Assembly.GetExecutingAssembly().Location.Replace("POS_Website.dll", string.Empty);
string ReportfullPath = Path.Join(fileDirPath, "\\Reports");
string JsonfullPath = Path.Join(fileDirPath,"\\JsonFiles");
string rdlcFilePath = string.Format("{0}\\{1}.rdlc", ReportfullPath, ReportName);
string generatedFilePath = string.Format("{0}\\{1}.pdf", JsonfullPath, guID);
string jsonDataFilePath = string.Format("{0}\\{1}.json", JsonfullPath, guID);
File.WriteAllText(jsonDataFilePath, JsonConvert.SerializeObject(DataSource));
FunctionExecutor.Run((string[] args) =>
{
// 0 : Data file path - jsonDataFilePath
// 1 : Filename - generatedFilePath
// 2 : RDLCPath - rdlcFilePath
ReportResult result;
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
Encoding.GetEncoding("windows-1252");
LocalReport report = new LocalReport(args[2]);
DataTable dt = JsonConvert.DeserializeObject<DataTable>(File.ReadAllText(args[0]));
report.AddDataSource(args[3], dt);
result = report.Execute(RenderType.Pdf, 1,Parameters);
using (var fs = new FileStream(args[1], FileMode.Create, FileAccess.Write))
{
fs.Write(result.MainStream);
}
}, new string[] {jsonDataFilePath, generatedFilePath, rdlcFilePath, DataSetName });
var memory = new MemoryStream();
using (var stream = new FileStream(Path.Combine("", generatedFilePath), FileMode.Open))
{
stream.CopyTo(memory);
}
File.Delete(generatedFilePath);
File.Delete(jsonDataFilePath);
memory.Position = 0;
return memory.ToArray();
}
But it throws exception "Field marshaling is not supported by ExecFunction" on line:
var result = reportService.GenerateReport(ReportName, param, "dsInvoiceDine", dt);
No Need to run report generation as a seperate process. Just Dont Pass extension as 1
in:
var result = localReport.Execute(RenderType.Pdf, 1, param);
The Solution is:
int ext = (int)(DateTime.Now.Ticks >> 10);
var result = localReport.Execute(RenderType.Pdf, ext, param);
I am writing code to create new test cases using rally restAPI.
Able to create the test cases under Test Plan & Test folder.
Now, want to map those test cases to Rally user stories.
Work product is the field to map it. But how to get the reference of user story using restAPI?
Please let me know if anyone has done in past.
In WS API user story is HierarchicalRequirement object. Query on the story, which you want to be a workproduct, and get its _ref. Then update the test case, e.g.
testCaseUpdate.addProperty("WorkProduct", storyRef);
Here is a Java example using Rally Rest toolkit for Java, but the approach is the same regardless of your choice of language or toolkit:
public class UpdateTestCase {
public static void main(String[] args) throws URISyntaxException, IOException {
String host = "https://rally1.rallydev.com";
String apiKey = "_abc123";
String workspaceRef = "/workspace/123456";
String applicationName = "RestExample_updateWorkProductOnTestCase";
RallyRestApi restApi = new RallyRestApi(new URI(host),apiKey);
restApi.setApplicationName(applicationName);
try {
String testid = "TC12";
String storyid = "US34";
QueryRequest testCaseRequest = new QueryRequest("TestCase");
testCaseRequest.setWorkspace(workspaceRef);
testCaseRequest.setFetch(new Fetch("FormattedID", "Name", "WorkProduct"));
testCaseRequest.setQueryFilter(new QueryFilter("FormattedID", "=", testid));
QueryResponse testCaseQueryResponse = restApi.query(testCaseRequest);;
if (testCaseQueryResponse.getTotalResultCount() == 0) {
System.out.println("Cannot find test case : " + testid);
return;
}
JsonObject testCaseJsonObject = testCaseQueryResponse.getResults().get(0).getAsJsonObject();
String testCaseRef = testCaseJsonObject.get("_ref").getAsString();
System.out.println(testCaseRef);
QueryRequest storyRequest = new QueryRequest("HierarchicalRequirement");
storyRequest.setWorkspace(workspaceRef);
storyRequest.setFetch(new Fetch("FormattedID", "Name"));
storyRequest.setQueryFilter(new QueryFilter("FormattedID", "=", storyid));
QueryResponse storyQueryResponse = restApi.query(storyRequest);;
if (storyQueryResponse.getTotalResultCount() == 0) {
System.out.println("Cannot find test story : " + storyid);
return;
}
JsonObject storyJsonObject = storyQueryResponse.getResults().get(0).getAsJsonObject();
String storyRef = storyJsonObject.get("_ref").getAsString();
System.out.println(storyRef);
JsonObject testCaseUpdate = new JsonObject();
testCaseUpdate.addProperty("WorkProduct", storyRef);
UpdateRequest updateTestCaseRequest = new UpdateRequest(testCaseRef,testCaseUpdate);
UpdateResponse updateTestCaseResponse = restApi.update(updateTestCaseRequest);
if (updateTestCaseResponse.wasSuccessful()) {
System.out.println("Successfully updated : " + testid + " WorkProduct after update: " + testCaseUpdate.get("WorkProduct"));
}
} finally {
restApi.close();
}
}
}
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?
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);
}
}
}
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!");
}
}
}
}