How to Manage Work Items Using Visual Studio Online REST API

TFS online as a part of Visual Studio Online ( VSO )  stays more and more popular solution for source control , backlog items management ( in the context of scrum and kanban ) , build system etc. Often software companies need to integrate work items management with other systems ( project management, billing etc.)

In the series of several blogs I will try to share my experience how to manage Visual Studio Programmatically.

In this article we will learn how to start to manage programmatically work items in Visual Studio Online. To do that you can use the VSO REST API calling it’s methods from any platform/language . Sometimes it is overhead to create own library to work with Visual Studio Online REST API. In this situation if you are using .NET / C# the best solution is just to use  Visual Studio Online REST API in codeplex .

Visual Studio Online REST API is a C# library for using TFS REST API in your .NET applications. Current version supports:

  • Projects and teams
  • Areas and iterations
  • Work item
  • Query and query folder
  • Version Control
  • Git
  • Build

This post is mainly focused on how to work with work items:

  • Create / update / read work items
  • Add / remove work item links and attachments
  • Create / update / delete tags

Before to start manage work items using Visual Studio Online REST API you need to do some preparations:

  • Prerequisites:

Authentication for the REST APIs:

These APIs support OAuth for authorization and you should plan to use that. With Oauth your users don’t have to provide their Visual Studio Online credentials to use when the APIs are called. To get started on your app, though, you can authenticate using basic authentication. You’ll have to enable alternate credentials to work with basic auth.

1. Open your profile

profile[1]

2. Enable alternate credentials on the credentials tab

enableCredentials[1]

3. Set your credentials

One appropriate place to do that are the application settings. It is possible of course to have a custom approach, but the samples from this blog assumes that you set there your credentials.

VSO-WorkItems-Pic01

 

VSO-WorkItems-Pic02

 Managing work items in Visual Studio Online

We will cover the main functionalities in the context of , regarding to the Visual Studio Online REST API

  • Get a team project description

One of the main features is to get the information for the VSO Team project, The code below shows how to do that,

   1: VsoClient _vsoClient;

   2: IVsoProject _client;

   3:  

   4: _vsoClient = new VsoClient(Properties.Settings.Default.AccountName, new NetworkCredential(Properties.Settings.Default.UserName, Properties.Settings.Default.Password));

   5: _client = _vsoClient.GetService<IVsoProject>();

   6:  

   7: var projects = _client.GetTeamProjects().Result;

   8: var project = _client.GetTeamProject(projects[0].Id.ToString(), true).Result;

   9: Console.Write("Project=" + project.ToString());

  10: Console.Write("\n");

  11: var descr = project.Description;

  12: Console.Write("Project Descr=" + descr);

 

The sample app is a console application. You can see the result screen below.

VSO-WorkItems-Pic03 

  • Getting the types of all work items

Another useful feature is how to get all   the types of the work items. It is possible for each item using the GetWorkItemType() method.

   1: _vsoClient = new VsoClient(Properties.Settings.Default.AccountName, new NetworkCredential(Properties.Settings.Default.UserName, Properties.Settings.Default.Password));

   2: _clientWit = _vsoClient.GetService<IVsoWit>();

   3:  

   4: var workItemTypes = _clientWit.GetWorkItemTypes(Properties.Settings.Default.ProjectName).Result;

   5: Console.Write("workItemTypes=" + workItemTypes.ToString());

   6: Console.Write("\n");

   7: for(int i = 0; i < workItemTypes.Count; i++)

   8: {

   9:     var workItemTypeEl = _clientWit.GetWorkItemType(Properties.Settings.Default.ProjectName, workItemTypes.Items[i].Name).Result;

  10:     Console.Write("workItemType["+i+"]=" + workItemTypeEl.ToString());

  11:     Console.Write("\n");

  12: }

  13: var workItemType = _clientWit.GetWorkItemType(Properties.Settings.Default.ProjectName, workItemTypes.Items[0].Name).Result;

  14:  Console.Write("workItemType[0]=" + workItemType.ToString());

  15: Console.Write("\n");

 

Below you can se the result in the console application:

VSO-WorkItems-Pic04

  • Get a field from a specified work item:
   1: VsoClient _vsoClient;

   2: IVsoWit _clientWit;

   3:  

   4: _vsoClient = new VsoClient(Properties.Settings.Default.AccountName, new NetworkCredential(Properties.Settings.Default.UserName, Properties.Settings.Default.Password));

   5: _clientWit = _vsoClient.GetService<IVsoWit>();

   6:  

   7: var fields = _clientWit.GetFields().Result;

   8: Console.Write("fields=" + fields.ToString());

   9: var field = _clientWit.GetField(fields.Items[0].ReferenceName).Result;

  10: Console.Write("field[0]=" + fields.ToString());

 

  • Get a specified backlog item:

It is possible to get a specified work item by work item id using GetWorkItem(workItemId) method

   1: VsoClient _vsoClient;

   2: IVsoWit _clientWit;

   3:  

   4: _vsoClient = new VsoClient(Properties.Settings.Default.AccountName, new NetworkCredential(Properties.Settings.Default.UserName, Properties.Settings.Default.Password));

   5: _clientWit = _vsoClient.GetService<IVsoWit>();

   6:  

   7: var workItem = _clientWit.GetWorkItem(170);

   8: Console.Write("workItem=" + workItem.ToString());

   9: Console.Write("\n");

  10: var witType = workItem.Result.Fields["System.WorkItemType"];

  11: Console.Write("WIT Type =" + witType.ToString());

  12: Console.Write("\n");

  13: var witAreaPath = workItem.Result.Fields["System.AreaPath"];

  14: Console.Write("WIT Area Path =" + witAreaPath.ToString());

  15: Console.Write("\n");

  16:  var witState = workItem.Result.Fields["System.State"];

  17:  Console.Write("WIT State =" + witState.ToString());

  18: Console.Write("\n");

  19:  var witTitle = workItem.Result.Fields["System.Title"];

  20:  Console.Write("WIT Title =" + witTitle.ToString());

  21: Console.Write("\n");

 

VSO-WorkItems-Pic05 

  • Create and execute queries in VSO / TFS Online using VSO REST API

Queries help you find work items that you want to review, triage, update, or generate a report.

Use the search box to find work items. Enter the ID or use filters. If you want a flat list of work items, a hierarchical list using a tree query, or a list showing dependencies using a direct links query, use the query editor to choose the query type.

You can create queries in Visual Studio Online, Team Web Access (TWA), and Team Explorer. Also, you can open a query in Excel or Project to perform bulk modifications.

   1: VsoClient _vsoClient;

   2: IVsoWit _clientWit;

   3:  

   4: _vsoClient = new VsoClient(Properties.Settings.Default.AccountName, new NetworkCredential(Properties.Settings.Default.UserName, Properties.Settings.Default.Password));

   5: _clientWit = _vsoClient.GetService<IVsoWit>()

   6:  

   7: const string LINK_QUERY = "Select System.Id, System.Title, System.State From WorkItems Where ([System.WorkItemType] = 'Product Backlog Item' AND [State] <> 'Closed' AND [State] <> 'Removed')";

   8: var ResultItems = _clientWit.RunFlatQuery(Properties.Settings.Default.ProjectName, LINK_QUERY).Result;

   9: for(int i =0; i < ResultItems.WorkItems.Count; i++)

  10: { 

  11:     var _id = ResultItems.WorkItems[i].Id;

  12:     Console.Write("\n");

  13:     Console.Write("WIT id =" + _id.ToString());

  14:     var _workItem = _clientWit.GetWorkItem(_id);

  15:     Console.Write("\n");

  16:     var _witAreaPath = _workItem.Result.Fields["System.AreaPath"];

  17:     Console.Write("WIT[" + _id  + "] Area Path =" + _witAreaPath.ToString());

  18:     Console.Write("\n");

  19:     var _witState = _workItem.Result.Fields["System.State"];

  20:     Console.Write("WIT[" + _id + "] State =" + _witState.ToString());

  21:     Console.Write("\n");

  22:     var _witTitle = _workItem.Result.Fields["System.Title"];

  23:     Console.Write("WIT[" + _id + "] Title =" + _witTitle.ToString());

  24:     Console.Write("\n");

  25: }

 

You can see the result in the test application console below:

VSO-WorkItems-Pic06

  • Create and update a work item

It is possible to use methods CreateWorkItem() and UpdateWorkItem() to create and update work items. The sample demo app demonstrates how to do that using the Visual Studio Online REST API. The initial state of the sample work items is shown below:

VSO-WorkItems-Pic07

Sample code also demonstrates how to create relations between work items:

   1: VsoClient _vsoClient;

   2: IVsoWit _clientWit;

   3:  

   4: _vsoClient = new VsoClient(Properties.Settings.Default.AccountName, new NetworkCredential(Properties.Settings.Default.UserName, Properties.Settings.Default.Password));

   5: _client = _vsoClient.GetService<IVsoWit>()

   6:  var orkItemId = 170;

   7: var workItems = _client.GetWorkItems(new int[] { workItemId }, RevisionExpandOptions.all).Result;

   8:  

   9: // Create new work item

  10: var bug = new WorkItem();

  11: bug.Fields["System.Title"] = "Sample bug N3";

  12: bug.Fields["System.History"] = DateTime.Now.ToString();

  13: bug = _client.CreateWorkItem(Properties.Settings.Default.ProjectName, "Bug", bug).Result;

  14:  

  15: var other = workItems[0];

  16:  

  17: // Update fields, add a link

  18: bug.Fields["System.Title"] = bug.Fields["System.Title"] + " (updated)";

  19: bug.Fields["System.Tags"] = "Demo Tag";

  20: Console.Write("\n");

  21: Console.Write("WIT id =" + workItemId.ToString());

  22: Console.Write("WIT[" + workItemId + "] Title =" + bug.Fields["System.Title"].ToString());

  23:  

  24: bug.Relations.Add(new WorkItemRelation()

  25: {

  26:     Url = other.Url,

  27:     Rel = "System.LinkTypes.Related",

  28:     Attributes = new RelationAttributes() { Comment = "Test Bug Relation" }

  29: });

  30:  

  31: bug = _client.UpdateWorkItem(bug).Result;

 

VSO-WorkItems-Pic08

The final result is shown below: a new bug: Sample Bug N3, updated and including a to another bug item.

VSO-WorkItems-Pic09

VSO-WorkItems-Pic09a 

  • Remove a work item ( bug)

It is also often seen case when you want to remove a work item. Actually it is not possible to remove it, but you can change the item state to “Removed”.

VSO-WorkItems-Pic10

   1: VsoClient _vsoClient;

   2: IVsoWit _client;

   3:  

   4: _vsoClient = new VsoClient(Properties.Settings.Default.AccountName, new NetworkCredential(Properties.Settings.Default.UserName, Properties.Settings.Default.Password));

   5: _client = _vsoClient.GetService<IVsoWit>()

   6:  

   7: const string LINK_QUERY = "Select System.Id, System.Title, System.State From WorkItems Where ([System.WorkItemType] = 'Bug')";

   8: var ResultItems3 = _client.RunFlatQuery(Properties.Settings.Default.ProjectName, LINK_QUERY).Result;

   9:  

  10: var workItemTitle = "Sample bug N2"

  11:  

  12: for (int i = 0; i < ResultItems3.WorkItems.Count; i++)

  13: {

  14:     var _id = ResultItems3.WorkItems[i].Id;

  15:     

  16:     Console.Write("\n");

  17:     Console.Write("WIT id =" + _id.ToString());

  18:     var _workItem = _client.GetWorkItem(_id).Result;

  19:     if (_workItem.Fields["System.Title"].ToString().Contains(workItemTitle))

  20:     {

  21:         Console.Write("\n");

  22:         var _witTitle = _workItem.Fields["System.Title"];

  23:         Console.Write("WIT[" + _id + "] Title =" + _witTitle.ToString());

  24:         Console.Write("\n");

  25:         var _witState = _workItem.Fields["System.State"];

  26:         

  27:         Console.Write("WIT[" + _id + "] State =" + _witState.ToString());

  28:         Console.Write("\n");

  29:         _workItem.Fields["System.State"] = "Removed";

  30:         var bug = _client.UpdateWorkItem(_workItem).Result;

  31:         Console.Write("\n");

  32:         _witState = _workItem.Fields["System.State"];

  33:         Console.Write("WIT[" + _id + "] Updated State =" + _witState.ToString());

  34:         Console.Write("\n");

  35:     }

  36:  

  37:  

  38: }

 

VSO-WorkItems-Pic11

The screen below shows the state after the execution of the last snippet: The item with the state, equal to “Removed” is not displayed in the list with work items:

VSO-WorkItems-Pic12

Below you can see the code of the whole application:

   1: using System;

   2: using System.Collections.Generic;

   3: using System.Linq;

   4: using System.Text;

   5: using System.Threading.Tasks;

   6: using System.Net;

   7: using VisualStudioOnline.Api.Rest.V1.Client;

   8: using VisualStudioOnline.Api.Rest.V1.Model;

   9:  

  10: namespace DemoApp

  11: {

  12:     class Program

  13:     {

  14:         static void Main(string[] args)

  15:         {

  16:             VsoClient _vsoClient;

  17:             IVsoProject _client;

  18:             IVsoWit _clientWit;

  19:  

  20:             _vsoClient = new VsoClient(Properties.Settings.Default.AccountName, new NetworkCredential(Properties.Settings.Default.UserName, Properties.Settings.Default.Password));

  21:             _client = _vsoClient.GetService<IVsoProject>();

  22:             _clientWit = _vsoClient.GetService<IVsoWit>();

  23:  

  24:  

  25:  

  26:             if (args != null)

  27:             {

  28:                 Console.WriteLine("args is null"); // Check for null array

  29:  

  30:                 var option = args[0];

  31:  

  32:                 switch (option)

  33:                 {

  34:                     case "firstproject":

  35:                         var projects = _client.GetTeamProjects().Result;

  36:                         var project = _client.GetTeamProject(projects[0].Id.ToString(), true).Result;

  37:                         Console.Write("Project=" + project.ToString());

  38:                         Console.Write("\n");

  39:                         var descr = project.Description;

  40:                         Console.Write("Project Descr=" + descr);

  41:                         break;

  42:  

  43:                     case "workitemtypes":

  44:                         var workItemTypes = _clientWit.GetWorkItemTypes(Properties.Settings.Default.ProjectName).Result;

  45:                         Console.Write("workItemTypes=" + workItemTypes.ToString());

  46:                         Console.Write("\n");

  47:                         for(int i = 0; i < workItemTypes.Count; i++)

  48:                         {

  49:                             var workItemTypeEl = _clientWit.GetWorkItemType(Properties.Settings.Default.ProjectName, workItemTypes.Items[i].Name).Result;

  50:                             Console.Write("workItemType["+i+"]=" + workItemTypeEl.ToString());

  51:                             Console.Write("\n");

  52:                         }

  53:                         var workItemType = _clientWit.GetWorkItemType(Properties.Settings.Default.ProjectName, workItemTypes.Items[0].Name).Result;

  54:                          Console.Write("workItemType[0]=" + workItemType.ToString());

  55:                         Console.Write("\n");

  56:  

  57:                         break;

  58:  

  59:                     case "getfields":

  60:                         var fields = _clientWit.GetFields().Result;

  61:                         Console.Write("fields=" + fields.ToString());

  62:                         var field = _clientWit.GetField(fields.Items[0].ReferenceName).Result;

  63:                         Console.Write("field[0]=" + fields.ToString());

  64:  

  65:                         break;

  66:                     case "getbacklogitem":

  67:                         var workItem = _clientWit.GetWorkItem(170);

  68:                         Console.Write("workItem=" + workItem.ToString());

  69:                         Console.Write("\n");

  70:                         var witType = workItem.Result.Fields["System.WorkItemType"];

  71:                         Console.Write("WIT Type =" + witType.ToString());

  72:                         Console.Write("\n");

  73:                         var witAreaPath = workItem.Result.Fields["System.AreaPath"];

  74:                         Console.Write("WIT Area Path =" + witAreaPath.ToString());

  75:                         Console.Write("\n");

  76:                          var witState = workItem.Result.Fields["System.State"];

  77:                          Console.Write("WIT State =" + witState.ToString());

  78:                         Console.Write("\n");

  79:                          var witTitle = workItem.Result.Fields["System.Title"];

  80:                          Console.Write("WIT Title =" + witTitle.ToString());

  81:                         Console.Write("\n");

  82:  

  83:                         break;

  84:  

  85:                     case "TestRunQuery":

  86:  

  87:                         const string LINK_QUERY2 = "Select System.Id, System.Title, System.State From WorkItems Where ([System.WorkItemType] = 'Product Backlog Item' AND [State] <> 'Closed' AND [State] <> 'Removed')";

  88:                         var ResultItems2 = _clientWit.RunFlatQuery(Properties.Settings.Default.ProjectName, LINK_QUERY2).Result;

  89:                         var _id2 = ResultItems2.WorkItems[0].Id;

  90:                         var _workItem2 = _clientWit.GetWorkItem(_id2);

  91:                         Console.Write("\n");

  92:                         var _witAreaPath2 = _workItem2.Result.Fields["System.AreaPath"];

  93:                         Console.Write("WIT Area Path =" + _witAreaPath2.ToString());

  94:                         Console.Write("\n");

  95:                         var _witState2 = _workItem2.Result.Fields["System.State"];

  96:                         Console.Write("WIT State =" + _witState2.ToString());

  97:                         Console.Write("\n");

  98:                         var _witTitle2 = _workItem2.Result.Fields["System.Title"];

  99:                         Console.Write("WIT Title =" + _witTitle2.ToString());

 100:                         Console.Write("\n");

 101:                         Console.Write("Flat Query Result =" + ResultItems2.ToString());

 102:                         Console.Write("\n");                        

 103:  

 104:                         break;

 105:                     case "TestRunQueries":

 106:  

 107:                         const string LINK_QUERY = "Select System.Id, System.Title, System.State From WorkItems Where ([System.WorkItemType] = 'Product Backlog Item' AND [State] <> 'Closed' AND [State] <> 'Removed')";

 108:                         var ResultItems = _clientWit.RunFlatQuery(Properties.Settings.Default.ProjectName, LINK_QUERY).Result;

 109:                         for(int i =0; i < ResultItems.WorkItems.Count; i++)

 110:                         { 

 111:                             var _id = ResultItems.WorkItems[i].Id;

 112:                             Console.Write("\n");

 113:                             Console.Write("WIT id =" + _id.ToString());

 114:                             var _workItem = _clientWit.GetWorkItem(_id);

 115:                             Console.Write("\n");

 116:                             var _witAreaPath = _workItem.Result.Fields["System.AreaPath"];

 117:                             Console.Write("WIT[" + _id  + "] Area Path =" + _witAreaPath.ToString());

 118:                             Console.Write("\n");

 119:                             var _witState = _workItem.Result.Fields["System.State"];

 120:                             Console.Write("WIT[" + _id + "] State =" + _witState.ToString());

 121:                             Console.Write("\n");

 122:                             var _witTitle = _workItem.Result.Fields["System.Title"];

 123:                             Console.Write("WIT[" + _id + "] Title =" + _witTitle.ToString());

 124:                             Console.Write("\n");

 125:                         }

 126:  

 127:                         break;

 128:  

 129:                     case "CreateAndUpdateWorkItem":

 130:  

 131:  

 132:  

 133:                         CreateAndUpdateWorkItem(_clientWit, 170);

 134:                         break;

 135:  

 136:                     case "RemoveBugItem":

 137:  

 138:                         RemoveBugItem(_clientWit, "Sample Bug N2");

 139:  

 140:                         break;

 141:  

 142:                 }

 143:             }

 144:             

 145:  

 146:             Console.ReadLine();

 147:  

 148:         }

 149:  

 150:         public static void CreateAndUpdateWorkItem(IVsoWit _client, int workItemId)

 151:         {

 152:             var workItems = _client.GetWorkItems(new int[] { workItemId }, RevisionExpandOptions.all).Result;

 153:  

 154:             // Create new work item

 155:             var bug = new WorkItem();

 156:             bug.Fields["System.Title"] = "Sample bug N3";

 157:             bug.Fields["System.History"] = DateTime.Now.ToString();

 158:             bug = _client.CreateWorkItem(Properties.Settings.Default.ProjectName, "Bug", bug).Result;

 159:  

 160:             var other = workItems[0];

 161:  

 162:             // Update fields, add a link

 163:             bug.Fields["System.Title"] = bug.Fields["System.Title"] + " (updated)";

 164:             bug.Fields["System.Tags"] = "Demo Tag";

 165:             Console.Write("\n");

 166:             Console.Write("WIT id =" + workItemId.ToString());

 167:             Console.Write("WIT[" + workItemId + "] Title =" + bug.Fields["System.Title"].ToString());

 168:  

 169:             bug.Relations.Add(new WorkItemRelation()

 170:             {

 171:                 Url = other.Url,

 172:                 Rel = "System.LinkTypes.Related",

 173:                 Attributes = new RelationAttributes() { Comment = "Test Bug Relation" }

 174:             });

 175:  

 176:             bug = _client.UpdateWorkItem(bug).Result;

 177:         }

 178:  

 179:  

 180:         public static void RemoveBugItem(IVsoWit _client, int workItemId)

 181:         {

 182:             //"Sample bug N2 (updated)"

 183:             const string LINK_QUERY = "Select System.Id, System.Title, System.State From WorkItems Where ([System.WorkItemType] = 'Bug' AND [State] <> 'Closed' AND [State] <> 'Removed')";

 184:             var ResultItems = _client.RunFlatQuery(Properties.Settings.Default.ProjectName, LINK_QUERY).Result;

 185:             var workItems = _client.GetWorkItems(new int[] { workItemId }, RevisionExpandOptions.all).Result;

 186:             // Create new work item

 187:             var bug = new WorkItem();

 188:             bug.Fields["System.Title"] = "Sample bug N3";

 189:             bug.Fields["System.History"] = DateTime.Now.ToString();

 190:             bug = _client.CreateWorkItem(Properties.Settings.Default.ProjectName, "Bug", bug).Result;

 191:  

 192:             var other = workItems[0];

 193:  

 194:             // Update fields, add a link

 195:             bug.Fields["System.Title"] = bug.Fields["System.Title"] + " (updated)";

 196:             bug.Fields["System.Tags"] = "Demo Tag";

 197:             Console.Write("\n");

 198:             Console.Write("WIT id =" + workItemId.ToString());

 199:             Console.Write("WIT[" + workItemId + "] Title =" + bug.Fields["System.Title"].ToString());

 200:  

 201:             bug.Relations.Add(new WorkItemRelation()

 202:             {

 203:                 Url = other.Url,

 204:                 //Rel = "System.LinkTypes.Dependency-Forward",

 205:                 Rel = "System.LinkTypes.Related",

 206:                 Attributes = new RelationAttributes() { Comment = "Test Буг Relation" }

 207:             });

 208:  

 209:             bug = _client.UpdateWorkItem(bug).Result;

 210:         }

 211:  

 212:         public static void RemoveBugItem(IVsoWit _client, string workItemTitle)

 213:         {

 214:             //"Sample bug N2 (updated)"

 215:             const string LINK_QUERY = "Select System.Id, System.Title, System.State From WorkItems Where ([System.WorkItemType] = 'Bug')";

 216:             var ResultItems3 = _client.RunFlatQuery(Properties.Settings.Default.ProjectName, LINK_QUERY).Result;

 217:  

 218:             for (int i = 0; i < ResultItems3.WorkItems.Count; i++)

 219:             {

 220:                 var _id = ResultItems3.WorkItems[i].Id;

 221:                 

 222:                 Console.Write("\n");

 223:                 Console.Write("WIT id =" + _id.ToString());

 224:                 var _workItem = _client.GetWorkItem(_id).Result;

 225:                 if (_workItem.Fields["System.Title"].ToString().Contains(workItemTitle))

 226:                 {

 227:                     Console.Write("\n");

 228:                     var _witTitle = _workItem.Fields["System.Title"];

 229:                     Console.Write("WIT[" + _id + "] Title =" + _witTitle.ToString());

 230:                     Console.Write("\n");

 231:                     var _witState = _workItem.Fields["System.State"];

 232:                     

 233:                     Console.Write("WIT[" + _id + "] State =" + _witState.ToString());

 234:                     Console.Write("\n");

 235:                     _workItem.Fields["System.State"] = "Removed";

 236:                     var bug = _client.UpdateWorkItem(_workItem).Result;

 237:                     Console.Write("\n");

 238:                     _witState = _workItem.Fields["System.State"];

 239:                     Console.Write("WIT[" + _id + "] Updated State =" + _witState.ToString());

 240:                     Console.Write("\n");

 241:                 }

 242:  

 243:  

 244:             }

 245:         }

 246:     }

 247: }

 

If you want more information about haw to manage programmatically  Visual Studio Online work otems feel free to contact me at michael@mateev.net Follow my blog : mmateev.infragistics.com  .

You can learn more about the PASS events if you follow me on Twitter @mihailmateev  , and stay in touch on Facebook, Google+, LinkedIn and Bulgarian BI and .Net User Group !

mvp

Advertisements

About Mihail Mateev

am a Microsoft Regional Director currently living in Sofia, Bulgaria. My interests range from technology to entrepreneurship. I am also interested in programming, web development, and education. Technical Consultant, Community enthusiast, PASS Regional Mentor for Central Eastern Europe, chapter lead, Microsoft MVP – Microsoft Azure. Organizer of SQLSaturday, Azure Bootcamp, IoT and JavaScript conferences. My experience is in various areas related to Microsoft technologies, including Windows Platform, ASP.Net MVC, MS SQL Server and Microsoft Azure. I have a PhD in cloud computing and am a university lecturer on Smart Homes and Smart Energy IoT Solutions
This entry was posted in .Net, Azure, C#, Cloud, Kanban, Microsoft Azure, Scrum, TFS, TFS Online, Visual Studio 2013, Visual Studio Online, VSO. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s