I'm looking around for a good example to work with TFS 2010 collections,projects, and workitems to start with.
I am able to iterate through collections and Projects using the following code (thanks to original coder)
Dim tfsServer As String = "http://test.domain.com:8080/tfs"
tfsServer = tfsServer.Trim()
Dim tfsUri As Uri
tfsUri = New Uri(tfsServer)
Dim configurationServer As New TfsConfigurationServer(tfsUri)
configurationServer = TfsConfigurationServerFactory.GetConfigurationServer(tfsUri)
' Get the catalog of team project collections
Dim collectionNodes As ReadOnlyCollection(Of CatalogNode)
Dim gVar As Guid() = New Guid() {CatalogResourceTypes.ProjectCollection}
collectionNodes = configurationServer.CatalogNode.QueryChildren(gVar, False, CatalogQueryOptions.None)
Dim strName As New StringBuilder
Dim strCollection As New StringBuilder
For Each collectionNode In collectionNodes
Dim collectionId As Guid = New Guid(collectionNode.Resource.Properties("InstanceID"))
strName.Length = 0
Dim teamProjectCollection As New TfsTeamProjectCollection(tfsUri)
teamProjectCollection = configurationServer.GetTeamProjectCollection(collectionId)
Response.Write("Collection:" & teamProjectCollection.Name & "<br/>")
' Get a catalog of team projects for the collection
Dim hVar As Guid() = New Guid() {CatalogResourceTypes.TeamProject}
Dim projectNodes As ReadOnlyCollection(Of CatalogNode)
projectNodes = collectionNode.QueryChildren(hVar, False, CatalogQueryOptions.None)
' List the team projects in the collection
For Each projectNode In projectNodes
strName.AppendLine(projectNode.Resource.DisplayName & "<br>")
'System.Console.WriteLine(" Team Project: " + projectNode.Resource.DisplayName)
Next
Response.Write(strName.ToString())
Next
I want to read specific project from a collection and iterate through workitems (tasks,bugs,issues,etc). Any help would be highly appreciated.
Thanks.
You can run any query you like in the teamProjectCollection - level with:
WorkItemStore workItemStore = (WorkItemStore)teamProjectCollection.GetService(typeof(WorkItemStore));
WorkItemCollection queryResults = workItemStore.Query(query);
foreach (WorkItem workitem in queryResults)
{
Console.WriteLine(workitem.Title);
}
Now you only have to formulate the query - string in something that provides you with what you need.
Queries are WIQL - like. This very basic can give you all work items within a TeamProject:
SELECT [System.Id], [System.WorkItemType], [System.Title], [System.AssignedTo], [System.State] FROM WorkItems WHERE [System.TeamProject] = #project
#project is in our case here the projectNode.Resource.DisplayName
(You can save any query you 've graphically set in TFS with 'Save as' as a *.wiq file & then use it's content programmatically)
Related
I'm using WorkItemTrackingHttpClient.QueryByWiqlAsync to retrieve the results of a query. It returns the top 200 records by default. It has a top param which you can use to specify a value less then 200.
However, the result of my query is greater than 200 records. Does anyone know how to execute a query using the TFS client with proper paging .i.e. page and page size? For example, return page 10 where the page count is say 50.
I've looked around but can't see how to do this using the client which is surprising as the capability seems so fundamental.
I'm using the Nuget Package Microsoft.TeamFoundationServer.Client 16.153.0. I'm also connecting to TFS 2017 onprem.
Yeah, we can only return a list of work items which limits to Maximum 200 by calling the API. It's by design, see Work Items - List for details.
However we can use WIQL Queries to retrieve data from Azure DevOps. It is very flexible and it could be used in any situation. See WIQL queries and Azure DevOps Rest API for WIQL Queries
To get all the work items, we can try following steps:
Execute a stored query using the work item query API to retrieve a
list of work item IDs
Split the list of work item IDs into groups of 200, which is the
maximum batch size that the work items API supports
Call the work items API for each list of 200 work item IDs to get
the work item details.
You can reference this thread for details.
Besides, below code for your reference, it's working for me:
using Microsoft.TeamFoundation.WorkItemTracking.WebApi;
using Microsoft.TeamFoundation.WorkItemTracking.WebApi.Models;
using Microsoft.VisualStudio.Services.Client;
using Microsoft.VisualStudio.Services.Common;
using System;
using System.Collections.Generic;
using System.Linq;
namespace QueryWorkitems0619
{
class Program
{
static void Main(string[] args)
{
Uri uri = new Uri("http://tfs2017:8080/tfs/DefaultCollection");
//string PAT = "xxxx";
string project = "SCRUM-TFVC";
//VssBasicCredential credentials = new VssBasicCredential(user, PAT);
VssCredentials credentials = new VssClientCredentials();
credentials.Storage = new VssClientCredentialStorage();
//create a wiql object and build our query
Wiql wiql = new Wiql()
{
Query = "Select * " +
"From WorkItems " +
"Where [Work Item Type] = 'Product Backlog Item' " +
"And [System.TeamProject] = '" + project + "' " +
"And [System.State] <> 'Closed' " +
"Order By [State] Asc, [Changed Date] Desc"
};
//create instance of work item tracking http client
using (WorkItemTrackingHttpClient workItemTrackingHttpClient = new WorkItemTrackingHttpClient(uri, credentials))
{
//execute the query to get the list of work items in the results
WorkItemQueryResult workItemQueryResult = workItemTrackingHttpClient.QueryByWiqlAsync(wiql).Result;
//Splict the query result (the list of work item IDs) into groups of 200.
var QueryGroups = from i in Enumerable.Range(0, workItemQueryResult.WorkItems.Count())
group workItemQueryResult.WorkItems.ToList()[i] by i / 200;
foreach (var QueryGroup in QueryGroups)
{
//some error handling
if (QueryGroup.Count() != 0)
{
//need to get the list of our work item ids and put them into an array
List<int> list = new List<int>();
foreach (var item in QueryGroup.ToList())
{
list.Add(item.Id);
}
int[] arr = list.ToArray();
//build a list of the fields we want to see
string[] fields = new string[3];
fields[0] = "System.Id";
fields[1] = "System.Title";
fields[2] = "System.State";
//get work items for the ids found in query
var workItems = workItemTrackingHttpClient.GetWorkItemsAsync(arr, fields, workItemQueryResult.AsOf).Result;
Console.WriteLine("\n\n----------------------------------------------------------------");
Console.WriteLine("\nQuery Results: {0} items found for Group {1}", workItems.Count, QueryGroup.Key);
Console.WriteLine("\n----------------------------------------------------------------");
//loop though work items and write to console
foreach (var workItem in workItems)
{
Console.WriteLine("ID:{0} Title:{1} State:{2}", workItem.Id, workItem.Fields["System.Title"], workItem.Fields["System.State"]);
}
}
}
Console.ReadLine();
}
}
}
}
I am looking for a query where i can return all work items and their relation from a area path.
for example : project 1
i need all Featured all Userstories mapped to it all workitem and Bug mapped to userstories,
in short if i took a bug from the object i need somthing like parent id where i can match with the userstory.
string query1 = " SELECT * FROM WorkItemLinks " +
" WHERE ( [System.IterationPath] Under 'iteration1' )" +
" AND ([System.Links.LinkType] = 'System.LinkTypes.Hierarchy-Forward' )" +
" ORDER BY [Microsoft.VSTS.Scheduling.StartDate]";
which throwing an error like below
An exception of type 'Microsoft.TeamFoundation.WorkItemTracking.Client.ValidationException' occurred in Microsoft.TeamFoundation.WorkItemTracking.Client.dll but was not handled in user code
Additional information: TF51005: The query references a field that does not exist. The error is caused by «[System.IterationPath]».
when i checked the dll's are refereed correctly and when i re wrote the query like this the query is working fine
string query = " SELECT * FROM WorkItems"+
" WHERE ( [System.IterationPath] Under 'iteration1' )" +
//" AND ([System.State] = 'Active' OR [System.State] = 'Assessed' ) "+
//" AND ( [Microsoft.VSTS.Scheduling.StartDate] <= '09/13/2017' AND [Microsoft.VSTS.Scheduling.FinishDate] >= '09/13/2017' )"+
" ORDER BY [Microsoft.VSTS.Scheduling.StartDate]";
but this query result does not give the relation ship that if a work item mapped as a child to other i need parent id in the work item object. how to get that. Thanks in advance.
You can try below query:
Install Nuget Package Microsoft.TeamFoundationServer.ExtendedClient for the project.
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.WorkItemTracking.Client;
using System;
namespace _0925_WIQL
{
class Program
{
static void Main(string[] args)
{
TfsTeamProjectCollection tpc = new TfsTeamProjectCollection(
new Uri("http://server:8080/tfs/CollectionLC"));
WorkItemStore workItemStore = (WorkItemStore)tpc.GetService(typeof(WorkItemStore));
string query1= " SELECT * FROM WorkItemLinks " +
" WHERE ( Source.[System.IterationPath] Under 'TeamProject\\Iteration 1' )" +
" AND ([System.Links.LinkType] = 'System.LinkTypes.Hierarchy-Forward' )" +
" ORDER BY [Microsoft.VSTS.Scheduling.StartDate]";
Query query = new Query(workItemStore, query1);
WorkItemLinkInfo[] witLinkInfos = query.RunLinkQuery();
foreach (WorkItemLinkInfo witinfo in witLinkInfos)
{
.......
}
Besides, you can also use Wiql Editor. If you want to get all the parent workitems (IDs) from a specific child work item (ID), you can use below WIQL:
SELECT
[System.Id],
[System.WorkItemType],
[System.Title],
[System.AssignedTo],
[System.State]
FROM workitemLinks
WHERE ([System.Links.LinkType] = 'System.LinkTypes.Hierarchy-Forward')
AND ([Target].[System.Id] = 25)
ORDER BY [System.Id]
MODE (Recursive, ReturnMatchingChildren)
Function GetStateName() As List(Of SelectListItem)
Dim ListRoomMaster As List(Of MiscMaster) = New List(Of MiscMaster)
Dim rm As New MiscMaster
Using conn As New SqlConnection(connectionString)
Dim sSql = "Select * From dropdown"
Dim cmd As SqlCommand = New SqlCommand(sSql, conn)
conn.Open()
Dim rst As SqlDataReader = cmd.ExecuteReader
Do While rst.Read
rm.m_ddlId = rst!id
rm.ddlValue = rst!name
ListRoomMaster.Add(rm)
Loop
End Using
Dim Listxyz = (
From p In Enumerable.Range(0, 20)
Select New SelectListItem With {.Text = p.ToString(), .Value = p.ToString()})
Return Listxyz.ToList()
End Function
This is the code for GetStateName() Which I am calling from controller Before Viewing This Displays The Drop Down List With 0 to 19 numbers I know I have Miss Something But Don't Know Where to change as most of code are for Linq
This Is Controller Code
Function Index() As ActionResult
objMisc.StateValue = objMisc.GetStateName()
'objMisc.StateValue = obj
Return View(objMisc)
End Function
What I Exactly Want Is Fetching data from DataBase using query
DataBase Have field like follow
id | Value
1 | xyz
2 | abx
3 | kvd
I want to populate drop down List As xyz,abx,kvd
And when abx is selected I want to store 2 in database
If you are working with MVC then you can also get the Data directly in the Razor View from your Model. Because you are doing a SQL Query manually which isnt the puropse of MVC.
Your should return the Model and then you can simply do this:
#Html.DropDownListFor(m => m.column, Model.dropdown)
Let's make a couple of models:
public NameCode(string name)
{
Name = name;
Code = name;
}
public NameCodeCollection(IEnumerable<NameCodeItem> list) : base(list)
{
}
In razor:
#Html.DropDownListFor(m => m.modelid, new SelectList(Model.modeltext, "Name", "Code"))
Use the namecodecollection to feed your dropdown list & read from it.
In TFS, some of work items are assigned. For those tasks test cases work items created and linked to the appropriate tasks.
I want to get the list of test cases linked for a particular task. How to write query to get it?
You have to use link query to get that:
SELECT [System.Id], [System.Title], [System.AssignedTo], [System.State]
FROM WorkItemLinks
WHERE ([Source].[System.TeamProject] = #project AND
[Source].[System.WorkItemType] = 'Test Case') And
([System.Links.LinkType] <> '') And ([Target].[System.Id] = #taskId)
ORDER BY [System.Id] mode(MayContain)
Here's the code to run it:
var tpc = new TfsTeamProjectCollection("http://localhost:8080/tfs/DefaultCollection");
var store = tpc.GetService<WorkItemStore>();
var queryContext = new Dictionary<string, string>();
queryContext.Add("project", "<team project name>");
queryContext.Add("taskId", "<task ID you are interested in>");
var query = new Query(store, "<WIQL query text>", queryContext);
var result = query.RunLinkQuery();
I've got the following WIQL query for a TFS project:
string query = "SELECT * FROM Issue WHERE [System.TeamProject] = #Project "+
"AND [Assigned To] IN (#AssignedTo)";
Dictionary<string, object> parameters = new Dictionary<string, object>();
parameters.Add("Project","test");
parameters.Add("AssignedTo","'chris','tfsuser'");
WorkItemStore.Query(query, parameters);
This is being run via the .NET TFS API.
My problem is with the AssignedTo parameter. How is this meant to be specified? I've tried it as a string[], List<string> as well as with and without quotes as above. Each one doesn't seem to work.
I understand what you're trying to do, but it doesn't look like it's possible. The query that you want is this:
WHERE [System.AssignedTo] in ('John Smith', 'Jane Citizen')
Which is semantically the same as this:
WHERE [System.AssignedTo] = 'John Smith' OR [System.AssignedTo] = 'Jane Citizen'
The only way I can work out how to achieve it in code is by specifying the identities as separate parameters:
TfsTeamProjectCollection tfs = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(new Uri("http://localhost:8080/tfs/"));
WorkItemStore wis = tfs.GetService<WorkItemStore>();
Dictionary<string, string> values = new Dictionary<string, string>();
values.Add("parameter1", "John Smith");
values.Add("parameter2", "Jane Citizen");
Query query = new Query(wis, "SELECT [System.Id] FROM WorkItems WHERE [System.AssignedTo] IN (#parameter1, #parameter2)", values);
WorkItemCollection workItems = wis.Query(query.QueryString);
WorkItem workItem = workItems[0];
Assigned To field is actually [System.AssignedTo]. I don't believe using the display name of the field will work.