TFS Custom Field Reporting on Historical Value - tfs

Using Agile template on with some customized fields.
Custom-Field-X is a Drop Down List with allowed value set 0, 1, 2, 3 - this value could change daily.
Need a way to check if Custom-Field-X was ever set to 0 during its life time.
Using TFS2010.
Thanks!

I assume you are talking about a custom field you added for TFS workitems. You can use following code to find out whether the value was set to 0 or not. Alternately you can also use workItemStore.GetWorkItem(id) to get specific workitem by Id. You can find details about retrieving work items # http://pwee167.wordpress.com/2012/09/18/retrieving-work-items-using-the-team-foundation-server-api/.
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.WorkItemTracking.Client; // You need to add reference to both these assemblies in your project
var collectionUri = new Uri("<TfsUrl>/<CollectionName>"); // For e.g. "http://tfs:8080/DefaultCollection"
var projectCollection = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(collectionUri);
WorkItemStore workItemStore = projectCollection.GetService<WorkItemStore>();
var results = workItemStore.Query("SELECT * FROM WORKITEMS");
WorkItem workItem = results[0];
foreach (Revision revision in workItem.Revisions)
{
var originalValue = revision.Fields["Custom-Field-X"].OriginalValue;
var curretValue = revision.Fields["Custom-Field-X"].Value;
}

Related

Can't preserve document core metadata (Created By, Modified By) when I import documents to SharePoint Document Library

I'm currently building a tool to migrate from a document management system to use SharePoint Online. The main challenge I'm facing is to preserve the details of document authors and creating time. I have checked bunch of of code online but I didn't get success with any of them.
Here are the approaches I used
SharePoint Rest API
Microsoft Graph API
CSOM (using console application)
Here is the code I have so far in CSOM but I'm still not able to update the Author field
li["Title"] = "Update from CSOM";
li["Created"] = DateTime.Now.AddYears(-5);
li["Author"] = author.Id;
li.UpdateOverwriteVersion();
clientContext.ExecuteQuery();
Any idea for how to do this, or if there is any other approach to achieve my goal?
The code works when I did test in my environment.
using (ClientContext context = new ClientContext("https://xxx.sharepoint.com/sites/lee"))
{
string s = "password";
SecureString passWord = new SecureString();
foreach (var c in s)
passWord.AppendChar(c);
context.Credentials = new SharePointOnlineCredentials("admin#xxx.onmicrosoft.com", passWord);
var author = context.Web.EnsureUser("Lee#xxx.onmicrosoft.com");
context.Load(author);
context.ExecuteQuery();
var _List = context.Web.Lists.GetByTitle("List1");
var li = _List.GetItemById(1);
li["Title"] = "Update from CSOM";
li["Created"] = DateTime.Now.AddYears(-5);
li["Author"] = author.Id;
li.UpdateOverwriteVersion();
context.ExecuteQuery();
}
You will need to update the Author and Editor fields at the same time in order to update the CreatedBy field. If you wish to update additional fields at the same time you can. Using SystemUpdate() does not update the Modified date whereas Update() does update the Modified date. See abbreviated sample below.
FieldUserValue userValue = new FieldUserValue();
User newUser = cc.Web.EnsureUser("newAuthor#xxx.onmicrosoft.com");
cc.Load(newUser);
cc.ExecuteQuery();
userValue.LookupId = newUser.Id;
item["Author"] = userValue;
item["Editor"] = userValue;
item.SystemUpdate();
cc.ExecuteQuery();

Creating default Userstorie or Tasks on creating a new iteration (TFS2013)

We work with TFS 2013 and every month we create a new iteration (vx.x.x.x etc). Every iteration has a standard set of Userstory's / tasks that need to be done to complete the iteration. Currently we need to create these workitems every month with the same data in them. Is there a way to automate this process? I was thinking about "Default work items" for an iteration, is that possible in TFS 2013?
Thanks in advance,
Tim
I don't think you can do it without writing some code. I suggest using TFS API and create some kind of tool which will create new iteration and required work items. E.g.
var tpc = new TfsTeamProjectCollection(new Uri("collection url, e.g. http://localhost:8080/tfs/DefaultCollection"));
var css = tpc.GetService<ICommonStructureService4>();
var store = tpc.GetService<WorkItemStore>();
var server = tpc.GetService<WorkItemServer>();
var project = store.Projects["MyProject"];
/*get root iteration node*/
NodeInfo rootIteration = css.ListStructures(project.Uri.ToString()).First(n => n.StructureType == "ProjectLifecycle");
/*create new iteration*/
css.CreateNode("TestIteration", rootIteration.Uri.ToString());
/*sync changes*/
server.SyncExternalStructures(WorkItemServer.NewRequestId(), project.Uri.ToString());
project.Store.RefreshCache();
/*create new bug in the new iteration*/
var bug = project.WorkItemTypes["Bug"].NewWorkItem();
bug.Title = "Test";
bug.AreaPath = "MyProject\\TestIteration";
bug.Save();

Access the Kanban Column (a Team-Specific Field) for a Work Item

Is there a way to programmatically access the "Kanban Column" for a WorkItem using the TFS 2012 API?
Using the Scrum 2.2 template, the history of a Bug or Product Backlog Item shows "[MyProject\MyTeam] Kanban Column" as a changed field whenever a work item is dragged between Kanban columns on the Board, but the field is not accessible when specifically retrieving a work item through the TFS API.
It also shows up as a changed field in the WorkItemChangedEvent object when implementing the ProcessEvent method on the Microsoft.TeamFoundation.Framework.Server.ISubscriber interface.
Workaround:
A coworker found a blogpost about creating a read-only custom field to persist the value of the Kanban Column, taking advantage of the WorkItemChangedEvent to capture the latest value. It is then possible to query on this column. One problem with this approach is that only a single team's Kanban Column can be tracked.
Update:
According to this blogpost, the Kanban Column is not a field, rather a "WIT Extension". This may help lead to an answer.
I've found a way to read the value using the TFS 2013 API, inside the ISubscriber.ProcessEvent method:
var workItemId = 12345;
var extService = new WorkItemTypeExtensionService();
var workItemService = new WorkItemService();
var wit = workItemService.GetWorkItem(requestContext, workItemId);
foreach (var wef in extService.GetExtensions(requestContext, wit.WorkItemTypeExtensionIds))
{
foreach (var field in wef.Fields)
{
if (field.LocalName == "Kanban Column" || field.LocalName == "Backlog items Column")
{
// Access the new column name
var columnName = wit.LatestData[field.Field.FieldId];
}
}
}
If you are prepared to dig into the database you can mine this information out. I don't fully understand the modelling of the teams in TFS yet but first you need to work out which field id the team of interest is storing the Kanban state in as follows (TFS 2012):
USE Tfs_DefaultCollection
SELECT TOP(10)
MarkerField + 1 as FieldId,*
FROM tbl_WorkItemTypeExtensions with(nolock)
JOIN tbl_projects on tbl_WorkItemTypeExtensions.ProjectId = tbl_projects.project_id
WHERE tbl_projects.project_name LIKE '%ProjectName%
Then replace XXXXXXXX below with the FieldId discovered above
SELECT TOP 1000
wid.Id,
wia.State,
wid.StringValue as Kanban,
wia.[Work Item Type],
wia.Title,
tn.Name as Iteration
FROM tbl_WorkItemData wid with(nolock)
JOIN WorkItemsAre wia on wia.ID = wid.Id
JOIN TreeNodes tn on wia.IterationID = tn.ID
WHERE FieldId = XXXXXXXX and RevisedDate = '9999-01-01 00:00:00.000'
ORDER BY Id
I am not familiar with the Scrum 2.2 template, but the works are the same for CMMI or Scrum templates when it comes to TFS Work Item tracking.
Try something like this:
public string GetKanbanColumn(WorkItem wi)
{
if (wi != null)
{
return wi["Kanban"].ToString();
}
return string.Empty;
}
Depending on the actual name of the column, specified in the Work Item Template XML file. Hope this helps.

query regarding TFS workitem

I want to know how I can update the field of my bug workitem. Suppose I need to change title of my bug workitem and after doing that I should get one pop up message box that my title field has changed without using email alerts? This is the query to select the workitem of a particular team project:
var tfs = TfsTeamProjectCollectionFactory.GetTeamProjectCollection
(new Uri("server url"));
var service = tfs.GetService<WorkItemStore>();
var qText = String.Format(#"SELECT [System.WorkItemType],
[System.Title], [System.Description], [System.Reason]
FROM WorkItems WHERE [System.TeamProject] = {0}", "'Demo1'");
I want to know the update query for changing the particular field.
Have you tried something like:
Dim workItemStore as WorkItemStore = tfs.GetService(Of WorkItemStore)()
Dim wi as WorkItem = workItemStore.GetWorkItem(workItemNumber)
wi.Fields("System.Title").Value = "Foo Title"
wi.Save()
I don't think WIQL supports dml commands. You are probably going to have to use the object model to do this: http://msdn.microsoft.com/en-us/library/bb130323.aspx

What tfs 2010 object references are available for Tfs_DefaultCollection.dbo.tbl_ReleaseNoteDetails

We have a Team Project Collection Source Control Setting for Check-in Notes that requires each check-in to capture a "Tracking Number". This number is external to TFS. I need to search for all the changesets that have a specific Tracking number.
The resulting changeset list tells me what to GetLatest on, for our monthly deployment.
-- We don't use Work Items
This .SQL gives me the list I'm looking for. I want to access this in code from Visual Studio.
SELECT ReleaseNoteId, FieldName, BaseValue
from Tfs_DefaultCollection.dbo.tbl_ReleaseNoteDetails
where ReleaseNoteId in (SELECT ReleaseNoteId
FROM Tfs_DefaultCollection.dbo.tbl_ReleaseNote
where DateCreated between '2013-01-01' and '2013-01-31')
and FieldName = 'Tracker #'
and BaseValue = '18570'
What object references are available for Tfs_DefaultCollection.dbo.tbl_ReleaseNoteDetails?
There is no 1to1 object reference in the TFS API, because you usually don't work on the structure like the database looks like.
What I understand from your description, you have the information you need in the changesets. In that case you could use the VersionControlServer to get the changesets and get the information from there.
TfsTeamProjectCollection tfsConnection = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(new Uri("http://TFS:8080/TFS/DefaultCollection"));
VersionControlServer sourceControl = (VersionControlServer)tfsConnection.GetService(typeof(VersionControlServer));
IEnumerable changesets = sourceControl.QueryHistory(ServerPath, VersionSpec.Latest, 0, RecursionType.Full, null, new DateVersionSpec (new DateTime(2013,1,1)), new DateVersionSpec (new DateTime(2013,1,31)), Int32.MaxValue, true, false);
foreach (Changeset change in changesets)
{
// check where the information is stored in the changeset, may change.Changes
}
Just an idea to get in the right direction.
If you want easy querying and searching, you're better off creating a new work item field and associate the work item during checkin. Work items have complete querying capabilities in the UI and are even transported to the Reporting warehouse.
You could retrieve the history for a specific folder, date range etc using a QueryHistoryParameters object and then iterate over the CheckinNotes to filter:
var projectCollection = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(
new Uri("http://localhost:8080/tfs/DefaultCollection"));
var versionControlServer = projectCollection.GetService<VersionControlServer>();
var query = new QueryHistoryParameters("$/Scrum/**", RecursionType.Full);
var changesets = server.QueryHistory(query);
changesets.Where(cs => cs.CheckinNotes.Any(note => note.PropertyName == "Tracker #"
&& note.Value == "18570"))
This is not going to be terribly fast. To get a quick solution, use work item association.

Resources