public Authenticate ( string username, string password, |
||
username | string | The user name to be used for access |
password | string | The password to be used for access |
serverUrl | The Rally server to use (defaults to DEFAULT_SERVER) | |
proxy | Optional proxy configuration | |
allowSSO | bool | Is SSO authentication allowed for this call? It can be useful to disable this during startup processes. |
return | AuthenticationResult |
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[] workspaces = new String[] { "/workspace/12352608129", "/workspace/34900020610" }; foreach (var s in workspaces) { Console.WriteLine(" ______________ " + s + " _________________"); Request typedefRequest = new Request("TypeDefinition"); typedefRequest.Workspace = s; typedefRequest.Fetch = new List<string>() { "ElementName", "Ordinal" }; typedefRequest.Query = new Query("Parent.Name", Query.Operator.Equals, "Portfolio Item"); QueryResult typedefResponse = restApi.Query(typedefRequest); foreach (var t in typedefResponse.Results) { if (t["Ordinal"] > -1) { Console.WriteLine("ElementName: " + t["ElementName"] + " Ordinal: " + t["Ordinal"]); } } } }
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/12352608129"; //String projectRef = "/project/39468725060"; Request request = new Request("Attachment"); request.Workspace = workspaceRef; //request.Project = projectRef; request.Fetch = new List<string>() { "Artifact", "TestCaseResult", "Size", "CreationDate" }; request.Limit = 400; request.Order = "CreationDate Desc"; QueryResult results = restApi.Query(request); foreach (var a in results.Results) { if (a["Artifact"] != null) { Console.WriteLine("Artifact: " + a["Artifact"]["_ref"]); } else if (a["TestCaseResult"] != null) { Console.WriteLine("TestCaseResult: " + a["TestCaseResult"]["_ref"]); } Console.WriteLine("Size: " + a["Size"]); } }
public RallyApi.RallyRestApi GetApi(string userName, string password) { int hash = (userName + "|" + password).GetHashCode(); if (Pools == null) { Pools = new Dictionary<int, RallyApi.RallyRestApi>(); } if (Pools.ContainsKey(hash) && Pools[hash].ConnectionInfo.UserName == userName && Pools[hash].ConnectionInfo.Password == password) { var conn = Pools[hash]; if (conn.ConnectionInfo != null && conn.AuthenticationState == RallyApi.RallyRestApi.AuthenticationResult.Authenticated) { return conn; } RallyApi.RallyRestApi.AuthenticationResult r = conn.Authenticate(userName, password, allowSSO:false); if (r != RallyApi.RallyRestApi.AuthenticationResult.Authenticated) { return null; } } RallyApi.RallyRestApi api = new RallyApi.RallyRestApi(); var result = api.Authenticate(userName, password, allowSSO:false); if (result != RallyApi.RallyRestApi.AuthenticationResult.Authenticated) { return null; } Pools.Add(hash, api); return api; }
public RallyApi.RallyRestApi GetApi(string userName, string password) { int hash = (userName + "|" + password).GetHashCode(); if (Pools == null) { Pools = new Dictionary <int, RallyApi.RallyRestApi>(); } if (Pools.ContainsKey(hash) && Pools[hash].ConnectionInfo.UserName == userName && Pools[hash].ConnectionInfo.Password == password) { var conn = Pools[hash]; if (conn.ConnectionInfo != null && conn.AuthenticationState == RallyApi.RallyRestApi.AuthenticationResult.Authenticated) { return(conn); } RallyApi.RallyRestApi.AuthenticationResult r = conn.Authenticate(userName, password, allowSSO: false); if (r != RallyApi.RallyRestApi.AuthenticationResult.Authenticated) { return(null); } } RallyApi.RallyRestApi api = new RallyApi.RallyRestApi(); var result = api.Authenticate(userName, password, allowSSO: false); if (result != RallyApi.RallyRestApi.AuthenticationResult.Authenticated) { return(null); } Pools.Add(hash, api); return(api); }
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/123"; String projectRef = "/project/456"; Request request = new Request("PortfolioItem/Feature"); request.Fetch = new List<string>() { "Name", "FormattedID" }; request.Query = new Query("FormattedID", Query.Operator.Equals, "F2356"); QueryResult result = restApi.Query(request); String featureRef = result.Results.First()._ref; Console.WriteLine("found" + featureRef); //create stories try { for (int i = 1; i <= 25; i++) { DynamicJsonObject story = new DynamicJsonObject(); story["Name"] = "story " + i; story["PlanEstimate"] = new Random().Next(2,10); story["PortfolioItem"] = featureRef; story["Project"] = projectRef; CreateResult createResult = restApi.Create(workspaceRef, "HierarchicalRequirement", story); story = restApi.GetByReference(createResult.Reference, "FormattedID"); Console.WriteLine("creating..." + story["FormattedID"]); } //read stories DynamicJsonObject feature = restApi.GetByReference(featureRef, "UserStories"); Request storiesRequest = new Request(feature["UserStories"]); storiesRequest.Fetch = new List<string>() { "FormattedID", "PlanEstimate" }; storiesRequest.Limit = 1000; QueryResult storiesResult = restApi.Query(storiesRequest); int storyCount = 0; foreach (var userStory in storiesResult.Results) { Console.WriteLine(userStory["FormattedID"] + " " + userStory["PlanEstimate"]); storyCount++; } Console.WriteLine(storyCount); } catch (Exception e) { Console.WriteLine(e); } }
static void Main(string[] args) { RallyRestApi restApi = new RallyRestApi(webServiceVersion: "v2.0"); String apiKey = "_abc777"; restApi.Authenticate(apiKey, "https://rally1.rallydev.com", allowSSO: false); String workspaceRef = "/workspace/123"; String projectRef = "/project/134"; DynamicJsonObject badDefect = new DynamicJsonObject(); badDefect["Name"] = "bad defect " + DateTime.Now; badDefect["Project"] = projectRef; CreateResult createRequest = restApi.Create(workspaceRef, "Defect", badDefect); badDefect = restApi.GetByReference(createRequest.Reference, "FormattedID", "Project"); Console.WriteLine(badDefect["FormattedID"] + " " + badDefect["Project"]._refObjectName); }
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/1011574887"; //non-default workspace of the user String projectRef = "/project/1791269111"; //a non-default project of the user (inside the workspace above) try { //create testset DynamicJsonObject myTestSet = new DynamicJsonObject(); myTestSet["Name"] = "important set " + DateTime.Now; myTestSet["Project"] = projectRef; CreateResult createTestSet = restApi.Create(workspaceRef, "TestSet", myTestSet); myTestSet = restApi.GetByReference(createTestSet.Reference, "FormattedID", "Project"); Console.WriteLine(myTestSet["FormattedID"] + " " + myTestSet["Project"]._refObjectName); //find current iteration Request iterationRequest = new Request("Iteration"); iterationRequest.Project = projectRef; iterationRequest.ProjectScopeDown = false; iterationRequest.ProjectScopeUp = false; iterationRequest.Fetch = new List<string>() { "ObjectID", "Name" }; iterationRequest.Query = new Query("(StartDate <= Today)").And(new Query("(EndDate >= Today)")); QueryResult queryResults = restApi.Query(iterationRequest); if (queryResults.TotalResultCount > 0) { Console.WriteLine(queryResults.Results.First()["Name"] + " " + queryResults.Results.First()["ObjectID"]); myTestSet["Iteration"] = queryResults.Results.First()._ref; OperationResult updateResult = restApi.Update(myTestSet["_ref"], myTestSet); } else { Console.WriteLine("No current iterations"); } } catch (Exception e) { Console.WriteLine(e); } }
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/32904827032"; try { //create story DynamicJsonObject myStory = new DynamicJsonObject(); myStory["Name"] = "another story " + DateTime.Now; myStory["Project"] = projectRef; CreateResult createStory = restApi.Create(workspaceRef, "HierarchicalRequirement", myStory); myStory = restApi.GetByReference(createStory.Reference, "FormattedID", "Project"); //update story myStory["Description"] = "updated " + DateTime.Now; myStory["c_CustomString"] = "abc123"; Console.WriteLine("--------------------"); Console.WriteLine(myStory["FormattedID"]); OperationResult updateResult = restApi.Update(myStory["_ref"], myStory); //create tasks for (int i = 1; i <= 3; i++) { DynamicJsonObject myTask = new DynamicJsonObject(); myTask["Name"] = "task " + i + DateTime.Now; myTask["State"] = "In-Progress"; myTask["WorkProduct"] = myStory["_ref"]; CreateResult createTask = restApi.Create(workspaceRef, "Task", myTask); myTask = restApi.GetByReference(createTask.Reference, "FormattedID", "Owner", "State"); Console.WriteLine(myTask["FormattedID"]); } } catch (Exception e) { Console.WriteLine(e); } }
static void Main(string[] args) { #region StartUp Section // Initialize all variables ConfigRallyUID = ""; ConfigRallyPWD = ""; ConfigLogPath = ""; ConfigStatusEOL = ""; ConfigReportPath = ""; ReportFile = ""; LogFile = ""; ConfigDBServer = ""; ConfigDBName = ""; ConfigDBUID = ""; ConfigDBPWD = ""; ReportDayNum = 0; ReportWeekNum = 0; ReportMonth = 0; ReportQuarter = 0; ReportYear = 0; // Get the configuration information from config file if (!GetConfigSettings()) { // If we can't get the configuration settings, we can't even log anything, so just terminate Environment.Exit(-1); } // Check for any commandline arguments. If there are not any, assume a "Daily" operating mode and set // the report date to yesterday (we don't want to report on today) if (args.Length != 0) { GetCommandArgs(); } else { OperatingMode = OperateMode.Daily; ReportingDay = DateTime.Today.AddDays(-1); ReportDayNum = ReportingDay.Day; ReportMonth = ReportingDay.Month; ReportYear = ReportingDay.Year; } #endregion StartUp Section // Log the start of processing LogOutput("Started processing at " + DateTime.Now.ToLongTimeString() + " on " + DateTime.Now.ToLongDateString(), "Main", false); DateTime dtStartTime = DateTime.Now; // Log the operating mode switch (OperatingMode) { case OperateMode.Daily: LogOutput("Operating in Daily Mode...Processing for Day " + ReportingDay.ToString("dd-MMM-yyyy"), "Main", false); break; case OperateMode.Monthly: LogOutput("Operating in Monthly Mode...Processing for " + ReportingDay.ToString("MMM"), "Main", false); break; case OperateMode.Quarterly: LogOutput("Operating in Quarterly mode...Processing for Quarter Q" + ReportQuarter.ToString() + "Y" + ReportYear.ToString(), "Main", false); break; case OperateMode.Annual: LogOutput("Operating in Annual mode...Processing for year " + ReportYear.ToString(), "Main", false); break; case OperateMode.Weekly: LogOutput("Operating in Weekly mode...Processing for Day " + ReportingDay.ToString("dd-MMM-yyyy"), "Main", false); break; default: LogOutput("Unknown Operating mode...assuming Daily...", "Main", false); break; } #region Gather from Rally // Create the Rally API object LogOutput("Creating reference to RallyAPI...", "Main", true); RallyAPI = new RallyRestApi(); // Login to Rally LogOutput("Starting connection to Rally...", "Main", true); try { RallyAPI.Authenticate(ConfigRallyUID, ConfigRallyPWD, ConfigRallyURL); LogOutput("Response from RallyAPI.Authenticate: " + RallyAPI.AuthenticationState.ToString(), "Main", true); if (RallyAPI.AuthenticationState.ToString() != "Authenticated") { // We did not actually connect LogOutput("Unable to connect to Rally and establish session. Application will terminate.", "Main", false); Environment.Exit(-1); } else { if (RallyAPI.ConnectionInfo.UserName == null) { LogOutput("RallyAPI.ConnectionInfo: " + RallyAPI.ConnectionInfo.ToString(), "Main", false); LogOutput("Unable to authenticate with Rally. Application will terminate.", "Main", false); Environment.Exit(-1); } else { LogOutput("Connected to Rally as user " + RallyAPI.ConnectionInfo.UserName, "Main", true); } } } catch (Exception ex) { LogOutput("Error Connecting to Rally: " + ex.Message, "Main", false); LogOutput("Rally Authentication State: " + RallyAPI.AuthenticationState.ToString() + "Rally Connection Info: " + RallyAPI.ConnectionInfo.ToString(), "Main", false); } // Grab the active Initiatives we want to report on LogOutput("Getting all Initiatives...", "Main", false); List<Initiative> InitiativeList = new List<Initiative>(); LogOutput("Calling 'GetInitiativeList'...", "Main", true); InitiativeList = GetInitiativeList(); LogOutput("Done with 'GetInitiativeList'", "Main", true); if (InitiativeList.Count == 0) { // Could not get the Initiatives...or nothing to report on, so stop LogOutput("Unable to open Initiative list or no Initiatives to report on. Application will terminate.", "Main", false); InitiativeList.Clear(); RallyAPI.Logout(); // Disconnect from Rally Environment.Exit(-1); // End Program } LogOutput("Retrieved " + InitiativeList.Count + " Initiatives to report on", "Main", false); // Now iterate through the initiatives and get all the Features or "Projects" LogOutput("Getting all Projects for the Initiatives...", "Main", false); BasicProjectList = new List<Project>(); LogOutput("Looping for each Initiative...", "Main", true); foreach (Initiative init in InitiativeList) { // Get the project list for the current initiative ONLY List<Project> ProjectList = new List<Project>(); LogOutput("Calling 'GetProjectsForInitiative' with " + init.Name.Trim() + "...", "Main", true); ProjectList = GetProjectsForInitiative(init.Name.Trim()); LogOutput("Done with 'GetProjectsForInitiative' for " + init.Name.Trim(), "Main", true); // Append this list to the FULL list LogOutput("Appending " + ProjectList.Count + " projects to object 'BasicProjectList'", "Main", true); BasicProjectList.AddRange(ProjectList); } LogOutput("Retrieved " + BasicProjectList.Count + " Projects total", "Main", false); // We need to loop through the project list now and for each project // we need to get all the epics. Then with each epic, we recursively // get all user stories LogOutput("Getting all User Stories for all projects...", "Main", false); // Initialize a new list of projects. This will become the full list including stories // and defects CompleteProjectList = new List<Project>(); LogOutput("Looping for each Project...", "Main", true); foreach (Project proj in BasicProjectList) { // Get all the epics for this project LogOutput("~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+", "Main", true); LogOutput("Calling 'GetEpicsForProject' with " + proj.Name.Trim() + "...", "Main", true); List<Epic> EpicList = new List<Epic>(); EpicList = GetEpicsForProject(proj.FormattedID.Trim()); LogOutput("Done with 'GetEpicsForProject' for " + proj.Name.Trim(), "Main", true); // Now go through each of the Epics for the current project // and recurse through to get all final-level user stories LogOutput("Getting all User Stories for " + proj.Name + "...", "Main", true); List<Epic> FullEpicList = new List<Epic>(); BasicStoryList = new List<UserStory>(); LogOutput("Looping for each Epic...", "Main", true); foreach (Epic epic in EpicList) { Epic newepic = new Epic(); List<UserStory> StoryList = new List<UserStory>(); LogOutput("Calling 'GetUserStoriesPerParent' with " + epic.FormattedID.Trim() + " as Root Parent...", "Main", true); StoryList = GetUserStoriesPerParent(epic.FormattedID.Trim(), epic.Name.Trim(), true); LogOutput("Done with 'GetUserStoriesPerParent' for " + epic.FormattedID.Trim(), "Main", true); // save the info as a new epic newepic.ActualEndDate = epic.ActualEndDate; newepic.DefectActual = epic.DefectActual; newepic.DefectEstimate = epic.DefectEstimate; newepic.DefectToDo = epic.DefectToDo; newepic.Description = epic.Description; newepic.FormattedID = epic.FormattedID; newepic.Name = epic.Name; newepic.Owner = epic.Owner; newepic.ParentProject = epic.ParentProject; newepic.PlannedEndDate = epic.PlannedEndDate; newepic.PlannedStartDate = epic.PlannedStartDate; newepic.Release = epic.Release; newepic.State = epic.State; newepic.StateChangedDate = epic.StateChangedDate; newepic.StoryActual = epic.StoryActual; newepic.StoryEstimate = epic.StoryEstimate; newepic.StoryToDo = epic.StoryToDo; newepic.UserStories = StoryList; // Add the stories to the full list FullEpicList.Add(newepic); BasicStoryList.AddRange(StoryList); } LogOutput("Retrieved " + BasicStoryList.Count + " User Stories for " + proj.Name, "Main", false); // Get any defects there may be for the User Stories LogOutput("Getting all Defects for " + proj.Name + "...", "Main", false); BasicDefectList = new List<Defect>(); LogOutput("Looping for each Story...", "Main", true); foreach (UserStory story in BasicStoryList) { List<Defect> DefectList = new List<Defect>(); // Defects will always be attached to a User Story LogOutput("Calling 'GetDefectsForStory' with " + story.Name + "...", "Main", true); DefectList = GetDefectsForStory(story); LogOutput("Done with 'GetDefectsForStory' for " + story.Name, "Main", true); // If there are any defects, add them to the list if (DefectList.Count > 0) { LogOutput("Appending " + DefectList.Count + " defects to object 'BasicDefectList'", "Main", true); BasicDefectList.AddRange(DefectList); } } // At this point we have the FULL list of User Stories/Defects for the current // project. We now create a "new" project with the same properties, but this time // we are able to store the Epics, User Stories, and Defects. LogOutput("Creating new project object and populating with full information...", "Main", true); Project newproject = new Project(); newproject.ActualEndDate = proj.ActualEndDate; newproject.Description = proj.Description; newproject.Expedite = proj.Expedite; newproject.FormattedID = proj.FormattedID; newproject.Initiative = proj.Initiative; newproject.LastUpdateDate = proj.LastUpdateDate; newproject.Name = proj.Name; newproject.OpportunityAmount = proj.OpportunityAmount; newproject.Owner = proj.Owner; newproject.UpdateOwner = proj.UpdateOwner; newproject.StakeHolder = proj.StakeHolder; newproject.PlannedEndDate = proj.PlannedEndDate; newproject.PlannedStartDate = proj.PlannedStartDate; newproject.RevokedReason = proj.RevokedReason; newproject.State = proj.State; newproject.StateChangedDate = proj.StateChangedDate; newproject.StatusUpdate = proj.StatusUpdate; newproject.UserStories = BasicStoryList; newproject.Defects = BasicDefectList; newproject.Epics = FullEpicList; LogOutput("Appending new project object to object 'CompleteProjectList'", "Main", true); CompleteProjectList.Add(newproject); } LogOutput("Done looping through all projects", "Main", false); LogOutput("Appending new project object to object 'CompleteProjectList'", "Main", true); #endregion Gather from Rally #region Calculation Section // We now have a full list of all projects with all complete information so // at this point we can calculate the Actuals for each project based on the reporting mode we are operating in switch (OperatingMode) { case OperateMode.Daily: // This mode runs every day and simply keeps running total of time with daily inserts for each project AllProjectInfo = new List<Project>(); LogOutput("Calling 'CalculateDailyTotals' with " + CompleteProjectList.Count + " complete projects...", "Main", true); AllProjectInfo = CalculateDailyTotals(CompleteProjectList, ReportingDay); LogOutput("Done with 'CalculateDailyTotals'", "Main", true); // Now create the final report LogOutput("Calling 'CreateDailyReport'...", "Main", true); CreateDailyReport(AllProjectInfo, ReportingDay); LogOutput("Done with 'CreateDailyReport'...", "Main", true); break; case OperateMode.Monthly: // This mode runs each month and creates very high-level summary info AllProjectInfo = new List<Project>(); LogOutput("Calling 'CalculateMonthlyReport' with " + CompleteProjectList.Count + " complete projects...", "Main", true); AllProjectInfo = CalculateMonthlyReport(CompleteProjectList, ReportMonth); LogOutput("Done with 'CalculateMonthlyReport'", "Main", true); // Now create the final report LogOutput("Calling 'CreateMonthlyReport'...", "Main", true); CreateMonthlyReport(AllProjectInfo, ReportMonth); LogOutput("Done with 'CreateMonthlyReport'...", "Main", true); break; case OperateMode.Quarterly: AllProjectInfo = new List<Project>(); LogOutput("Calling 'CalculateQuarterTotals' with " + CompleteProjectList.Count + " complete projects...", "Main", true); AllProjectInfo = CalculateQuarterTotals(CompleteProjectList, ReportQuarter, ReportYear); LogOutput("Done with 'CalculateQuarterTotals'", "Main", true); // Now create the final report LogOutput("Calling 'CreateQuarterReport'...", "Main", true); CreateQuarterReport(AllProjectInfo, ReportYear.ToString() + 'Q' + ReportQuarter.ToString()); LogOutput("Done with 'CreateQuarterReport'...", "Main", true); break; case OperateMode.Annual: AllProjectInfo = new List<Project>(); LogOutput("Calling 'CalculateAnnualTotals' with " + CompleteProjectList.Count + " complete projects...", "Main", true); AllProjectInfo = CalculateAnnualTotals(CompleteProjectList, ReportYear); LogOutput("Done with 'CalculateAnnualTotals'", "Main", true); // Now create the final report LogOutput("Calling 'CreateAnnualReport'...", "Main", true); CreateAnnualReport(AllProjectInfo, ReportYear); LogOutput("Done with 'CreateAnnualReport'...", "Main", true); break; case OperateMode.Weekly: // This mode is intended to run on Sunday in order to run stats for up-to-and-including current week for projects. The "Project Update" // is also included so the single table can be queried AllProjectInfo = new List<Project>(); LogOutput("Calling 'CalculateWeeklyTotals' with " + CompleteProjectList.Count + " complete projects...", "Main", true); AllProjectInfo = CalculateWeeklyTotals(CompleteProjectList, ReportingDay); LogOutput("Done with 'CalculateWeeklyTotals'", "Main", true); // Now create the weekly report LogOutput("Calling 'CreateWeeklyReport'...", "Main", true); CreateWeeklyReport(AllProjectInfo, ReportingDay); LogOutput("Done with 'CreateWeeklyReport'...", "Main", true); break; } #endregion DateTime dtEndTime = DateTime.Now; string strTotSeconds = dtEndTime.Subtract(dtStartTime).TotalSeconds.ToString(); LogOutput("Completed processing at " + DateTime.Now.ToLongTimeString() + " on " + DateTime.Now.ToLongDateString() + " - Total Processing Time: " + strTotSeconds + " seconds", "Main", false); Environment.Exit(0); }
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/1011574887"; String projectRef = "/project/1791269111"; String userName = "******"; try { Request storyRequest = new Request("hierarchicalrequirement"); storyRequest.Workspace = workspaceRef; storyRequest.Project = projectRef; storyRequest.Fetch = new List<string>() { "FormattedID" }; storyRequest.Query = new Query("FormattedID", Query.Operator.Equals, "US2917"); QueryResult queryResult = restApi.Query(storyRequest); var storyObject = queryResult.Results.First(); String storyReference = storyObject["_ref"]; Request userRequest = new Request("user"); userRequest.Fetch = new List<string>() { "UserName" }; userRequest.Query = new Query("UserName", Query.Operator.Equals, userName); QueryResult queryUserResults = restApi.Query(userRequest); DynamicJsonObject user = new DynamicJsonObject(); user = queryUserResults.Results.First(); String userRef = user["_ref"]; String imageFilePath = "C:\\images\\"; String imageFileName = "rally.png"; String fullImageFile = imageFilePath + imageFileName; Image myImage = Image.FromFile(fullImageFile); string imageBase64String = ImageToBase64(myImage, System.Drawing.Imaging.ImageFormat.Png); var imageNumberBytes = Convert.FromBase64String(imageBase64String).Length; Console.WriteLine("Image size: " + imageNumberBytes); DynamicJsonObject myAttachmentContent = new DynamicJsonObject(); myAttachmentContent["Content"] = imageBase64String; CreateResult myAttachmentContentCreateResult = restApi.Create(workspaceRef,"AttachmentContent", myAttachmentContent); String myAttachmentContentRef = myAttachmentContentCreateResult.Reference; Console.WriteLine(myAttachmentContentRef); DynamicJsonObject myAttachment = new DynamicJsonObject(); myAttachment["Artifact"] = storyReference; myAttachment["Content"] = myAttachmentContentRef; myAttachment["Name"] = "rally.png"; myAttachment["Description"] = "Attachment Desc"; myAttachment["ContentType"] = "image/png"; myAttachment["Size"] = imageNumberBytes; myAttachment["User"] = userRef; CreateResult myAttachmentCreateResult = restApi.Create(workspaceRef, "Attachment", myAttachment); List<string> createErrors = myAttachmentContentCreateResult.Errors; for (int i = 0; i < createErrors.Count; i++) { Console.WriteLine(createErrors[i]); } String myAttachmentRef = myAttachmentCreateResult.Reference; Console.WriteLine(myAttachmentRef); } catch (Exception e) { Console.WriteLine(e); } }