├── Bot ├── .gitattributes ├── .gitignore ├── Debugger │ ├── App.config │ ├── Debugger.csproj │ ├── Program.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ └── packages.config ├── VSTF_RD_Bot.sln └── VSTF_RD_Bot │ ├── App_Start │ └── WebApiConfig.cs │ ├── Constants │ └── Constants.cs │ ├── Controllers │ ├── LogicAppController.cs │ ├── LoginController.cs │ └── MessagesController.cs │ ├── DIalog │ └── VSTFDialog.cs │ ├── Global.asax │ ├── Global.asax.cs │ ├── Models │ ├── Command.cs │ ├── QueryItem.cs │ ├── TFSItem.cs │ └── TFSResponse.cs │ ├── Properties │ └── AssemblyInfo.cs │ ├── VSTF_RD_Bot.csproj │ ├── Web.Debug.config │ ├── Web.Release.config │ ├── Web.config │ ├── default.htm │ ├── loggedin.htm │ └── packages.config ├── LICENSE ├── Logic_Apps ├── Bot_Create_VSTF.json ├── Bot_ExecuteCommand_VSTF.json └── Bot_Search_VSTF.json ├── README.md └── VSTS_API ├── .gitattributes ├── .gitignore ├── VSTS_API.Tests ├── Properties │ └── AssemblyInfo.cs ├── UnitTest1.cs ├── VSTS_API.Tests.csproj ├── app.config └── packages.config ├── VSTS_API.sln └── VSTS_API ├── App_Start ├── SwaggerConfig.cs ├── Utils.cs └── WebApiConfig.cs ├── Controllers ├── CreateItemController.cs ├── ExecuteQueryController.cs └── SearchItemController.cs ├── Global.asax ├── Global.asax.cs ├── Models └── SimpleWorkItem.cs ├── Properties ├── AssemblyInfo.cs ├── Resources.Designer.cs └── Resources.resx ├── VSTS_API.csproj ├── Web.Debug.config ├── Web.Release.config ├── Web.config └── packages.config /Bot/.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /Bot/.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | build/ 21 | bld/ 22 | [Bb]in/ 23 | [Oo]bj/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | 28 | # MSTest test Results 29 | [Tt]est[Rr]esult*/ 30 | [Bb]uild[Ll]og.* 31 | 32 | # NUNIT 33 | *.VisualState.xml 34 | TestResult.xml 35 | 36 | # Build Results of an ATL Project 37 | [Dd]ebugPS/ 38 | [Rr]eleasePS/ 39 | dlldata.c 40 | 41 | # DNX 42 | project.lock.json 43 | artifacts/ 44 | 45 | *_i.c 46 | *_p.c 47 | *_i.h 48 | *.ilk 49 | *.meta 50 | *.obj 51 | *.pch 52 | *.pdb 53 | *.pgc 54 | *.pgd 55 | *.rsp 56 | *.sbr 57 | *.tlb 58 | *.tli 59 | *.tlh 60 | *.tmp 61 | *.tmp_proj 62 | *.log 63 | *.vspscc 64 | *.vssscc 65 | .builds 66 | *.pidb 67 | *.svclog 68 | *.scc 69 | 70 | # Chutzpah Test files 71 | _Chutzpah* 72 | 73 | # Visual C++ cache files 74 | ipch/ 75 | *.aps 76 | *.ncb 77 | *.opensdf 78 | *.sdf 79 | *.cachefile 80 | 81 | # Visual Studio profiler 82 | *.psess 83 | *.vsp 84 | *.vspx 85 | 86 | # TFS 2012 Local Workspace 87 | $tf/ 88 | 89 | # Guidance Automation Toolkit 90 | *.gpState 91 | 92 | # ReSharper is a .NET coding add-in 93 | _ReSharper*/ 94 | *.[Rr]e[Ss]harper 95 | *.DotSettings.user 96 | 97 | # JustCode is a .NET coding add-in 98 | .JustCode 99 | 100 | # TeamCity is a build add-in 101 | _TeamCity* 102 | 103 | # DotCover is a Code Coverage Tool 104 | *.dotCover 105 | 106 | # NCrunch 107 | _NCrunch_* 108 | .*crunch*.local.xml 109 | 110 | # MightyMoose 111 | *.mm.* 112 | AutoTest.Net/ 113 | 114 | # Web workbench (sass) 115 | .sass-cache/ 116 | 117 | # Installshield output folder 118 | [Ee]xpress/ 119 | 120 | # DocProject is a documentation generator add-in 121 | DocProject/buildhelp/ 122 | DocProject/Help/*.HxT 123 | DocProject/Help/*.HxC 124 | DocProject/Help/*.hhc 125 | DocProject/Help/*.hhk 126 | DocProject/Help/*.hhp 127 | DocProject/Help/Html2 128 | DocProject/Help/html 129 | 130 | # Click-Once directory 131 | publish/ 132 | 133 | # Publish Web Output 134 | *.[Pp]ublish.xml 135 | *.azurePubxml 136 | ## TODO: Comment the next line if you want to checkin your 137 | ## web deploy settings but do note that will include unencrypted 138 | ## passwords 139 | #*.pubxml 140 | 141 | *.publishproj 142 | 143 | # NuGet Packages 144 | *.nupkg 145 | # The packages folder can be ignored because of Package Restore 146 | **/packages/* 147 | # except build/, which is used as an MSBuild target. 148 | !**/packages/build/ 149 | # Uncomment if necessary however generally it will be regenerated when needed 150 | #!**/packages/repositories.config 151 | 152 | # Windows Azure Build Output 153 | csx/ 154 | *.build.csdef 155 | 156 | # Windows Store app package directory 157 | AppPackages/ 158 | 159 | # Visual Studio cache files 160 | # files ending in .cache can be ignored 161 | *.[Cc]ache 162 | # but keep track of directories ending in .cache 163 | !*.[Cc]ache/ 164 | 165 | # Others 166 | ClientBin/ 167 | [Ss]tyle[Cc]op.* 168 | ~$* 169 | *~ 170 | *.dbmdl 171 | *.dbproj.schemaview 172 | *.pfx 173 | *.publishsettings 174 | node_modules/ 175 | orleans.codegen.cs 176 | 177 | # RIA/Silverlight projects 178 | Generated_Code/ 179 | 180 | # Backup & report files from converting an old project file 181 | # to a newer Visual Studio version. Backup files are not needed, 182 | # because we have git ;-) 183 | _UpgradeReport_Files/ 184 | Backup*/ 185 | UpgradeLog*.XML 186 | UpgradeLog*.htm 187 | 188 | # SQL Server files 189 | *.mdf 190 | *.ldf 191 | 192 | # Business Intelligence projects 193 | *.rdl.data 194 | *.bim.layout 195 | *.bim_*.settings 196 | 197 | # Microsoft Fakes 198 | FakesAssemblies/ 199 | 200 | # Node.js Tools for Visual Studio 201 | .ntvs_analysis.dat 202 | 203 | # Visual Studio 6 build log 204 | *.plg 205 | 206 | # Visual Studio 6 workspace options file 207 | *.opt 208 | 209 | # LightSwitch generated files 210 | GeneratedArtifacts/ 211 | _Pvt_Extensions/ 212 | ModelManifest.xml 213 | -------------------------------------------------------------------------------- /Bot/Debugger/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /Bot/Debugger/Debugger.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {66A0B88F-3CB3-4994-9AB9-F01F32848DE9} 8 | Exe 9 | Properties 10 | Debugger 11 | Debugger 12 | v4.6.1 13 | 512 14 | true 15 | 16 | 17 | 18 | AnyCPU 19 | true 20 | full 21 | false 22 | bin\Debug\ 23 | DEBUG;TRACE 24 | prompt 25 | 4 26 | 27 | 28 | AnyCPU 29 | pdbonly 30 | true 31 | bin\Release\ 32 | TRACE 33 | prompt 34 | 4 35 | 36 | 37 | 38 | ..\packages\Microsoft.Bot.Builder.1.0.1.0\lib\net45\Microsoft.Bot.Builder.dll 39 | True 40 | 41 | 42 | ..\packages\Microsoft.Bot.Connector.1.0.0.0\lib\net45\Microsoft.Bot.Connector.dll 43 | True 44 | 45 | 46 | ..\packages\Microsoft.Bot.Connector.1.0.0.0\lib\net45\Microsoft.Bot.Connector.Utilities.dll 47 | True 48 | 49 | 50 | ..\packages\Microsoft.Rest.ClientRuntime.1.8.2\lib\net45\Microsoft.Rest.ClientRuntime.dll 51 | True 52 | 53 | 54 | ..\packages\Microsoft.WindowsAzure.ConfigurationManager.3.1.0\lib\net40\Microsoft.WindowsAzure.Configuration.dll 55 | True 56 | 57 | 58 | ..\packages\Newtonsoft.Json.8.0.3\lib\net45\Newtonsoft.Json.dll 59 | True 60 | 61 | 62 | 63 | 64 | 65 | ..\packages\Microsoft.AspNet.WebApi.Client.5.2.3\lib\net45\System.Net.Http.Formatting.dll 66 | True 67 | 68 | 69 | 70 | ..\packages\Microsoft.AspNet.WebApi.Core.5.2.3\lib\net45\System.Web.Http.dll 71 | True 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | {a8ba1066-5695-4d71-abb4-65e5a5e0c3d4} 91 | VSTF_RD_Bot 92 | 93 | 94 | 95 | 102 | -------------------------------------------------------------------------------- /Bot/Debugger/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Bot.Builder.Dialogs; 2 | using Microsoft.Bot.Connector; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace Debugger 10 | { 11 | class Program 12 | { 13 | static void Main(string[] args) 14 | { 15 | Interactive(new VSTF_RD_Bot.VSTFDialog()); 16 | } 17 | 18 | static void Interactive(IDialog form) 19 | { 20 | var message = new Message() 21 | { 22 | ConversationId = Guid.NewGuid().ToString(), 23 | Text = "" 24 | }; 25 | string prompt; 26 | do 27 | { 28 | var task = Conversation.SendAsync(message, () => form); 29 | message = task.GetAwaiter().GetResult(); 30 | prompt = message.Text; 31 | if (prompt != null) 32 | { 33 | Console.WriteLine(prompt); 34 | Console.Write("> "); 35 | message.Text = Console.ReadLine(); 36 | } 37 | } while (prompt != null); 38 | } 39 | 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Bot/Debugger/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Debugger")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("Debugger")] 13 | [assembly: AssemblyCopyright("Copyright © 2016")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("66a0b88f-3cb3-4994-9ab9-f01f32848de9")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /Bot/Debugger/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /Bot/VSTF_RD_Bot.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.24720.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VSTF_RD_Bot", "VSTF_RD_Bot\VSTF_RD_Bot.csproj", "{A8BA1066-5695-4D71-ABB4-65E5A5E0C3D4}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Debugger", "Debugger\Debugger.csproj", "{66A0B88F-3CB3-4994-9AB9-F01F32848DE9}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Release|Any CPU = Release|Any CPU 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {A8BA1066-5695-4D71-ABB4-65E5A5E0C3D4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 17 | {A8BA1066-5695-4D71-ABB4-65E5A5E0C3D4}.Debug|Any CPU.Build.0 = Debug|Any CPU 18 | {A8BA1066-5695-4D71-ABB4-65E5A5E0C3D4}.Release|Any CPU.ActiveCfg = Release|Any CPU 19 | {A8BA1066-5695-4D71-ABB4-65E5A5E0C3D4}.Release|Any CPU.Build.0 = Release|Any CPU 20 | {66A0B88F-3CB3-4994-9AB9-F01F32848DE9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {66A0B88F-3CB3-4994-9AB9-F01F32848DE9}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {66A0B88F-3CB3-4994-9AB9-F01F32848DE9}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {66A0B88F-3CB3-4994-9AB9-F01F32848DE9}.Release|Any CPU.Build.0 = Release|Any CPU 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | EndGlobal 29 | -------------------------------------------------------------------------------- /Bot/VSTF_RD_Bot/App_Start/WebApiConfig.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using Newtonsoft.Json.Serialization; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Web.Http; 7 | 8 | namespace VSTF_RD_Bot 9 | { 10 | public static class WebApiConfig 11 | { 12 | public static void Register(HttpConfiguration config) 13 | { 14 | // Json settings 15 | config.Formatters.JsonFormatter.SerializerSettings.NullValueHandling = NullValueHandling.Ignore; 16 | config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); 17 | config.Formatters.JsonFormatter.SerializerSettings.Formatting = Formatting.Indented; 18 | JsonConvert.DefaultSettings = () => new JsonSerializerSettings() 19 | { 20 | ContractResolver = new CamelCasePropertyNamesContractResolver(), 21 | Formatting = Newtonsoft.Json.Formatting.Indented, 22 | NullValueHandling = NullValueHandling.Ignore, 23 | }; 24 | 25 | // Web API configuration and services 26 | 27 | // Web API routes 28 | config.MapHttpAttributeRoutes(); 29 | 30 | config.Routes.MapHttpRoute( 31 | name: "DefaultApi", 32 | routeTemplate: "api/{controller}/{id}", 33 | defaults: new { id = RouteParameter.Optional } 34 | ); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Bot/VSTF_RD_Bot/Constants/Constants.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Configuration; 4 | using System.Linq; 5 | using System.Web; 6 | 7 | namespace VSTF_RD_Bot 8 | { 9 | public static class Constants 10 | { 11 | #region LUIS Constants 12 | 13 | internal static string Type_Entity = "Type"; 14 | 15 | internal static string Query_Entity = "Query"; 16 | 17 | internal static string Title_Entity = "Title"; 18 | 19 | internal const string LUIS_AppId = "Your APP ID"; 20 | internal const string LUIS_AppSecret = "Your App Secret"; 21 | 22 | #endregion 23 | 24 | #region 25 | 26 | internal static string LogicAppQueryUrl = ConfigurationManager.AppSettings["logicAppQueryUrl"]; 27 | internal static string LogicAppCreateUrl = ConfigurationManager.AppSettings["logicAppCreateUrl"]; 28 | internal static string LogicAppCommandUrl = ConfigurationManager.AppSettings["logicAppCommandUrl"]; 29 | 30 | internal static string ADClientId = ConfigurationManager.AppSettings["ADClientId"]; 31 | 32 | internal static string ADClientSecret = ConfigurationManager.AppSettings["ADClientSecret"]; 33 | 34 | internal static string apiBasePath = ConfigurationManager.AppSettings["apiBasePath"].ToLower(); 35 | 36 | internal static string botId = ConfigurationManager.AppSettings["AppId"]; 37 | 38 | internal static string botSecret = ConfigurationManager.AppSettings["AppSecret"]; 39 | internal static string regex_create = "\\s(.*):\\s?(.*)"; 40 | internal static string regex_command = "^\\/(\\w*)\\s*"; 41 | 42 | #endregion 43 | } 44 | 45 | } -------------------------------------------------------------------------------- /Bot/VSTF_RD_Bot/Controllers/LogicAppController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Net; 5 | using System.Net.Http; 6 | using System.Threading.Tasks; 7 | using System.Web.Http; 8 | using VSTF_RD_Bot.Models; 9 | 10 | namespace VSTF_RD_Bot.Controllers 11 | { 12 | public class LogicAppController : ApiController 13 | { 14 | [HttpGet, Route("api/vstf/search")] 15 | public async Task SearchVSTF(QueryItem query) 16 | { 17 | using (var client = new HttpClient()) 18 | { 19 | var response = await client.PostAsJsonAsync(Constants.LogicAppQueryUrl, query); 20 | return response; 21 | } 22 | } 23 | 24 | [HttpPost, Route("api/vstf")] 25 | public async Task CreateVSTF(TFSItem item) 26 | { 27 | using (var client = new HttpClient()) 28 | { 29 | var response = await client.PostAsJsonAsync(Constants.LogicAppCreateUrl, item); 30 | return response; 31 | } 32 | } 33 | 34 | internal async Task ExecuteCommand(Command command) 35 | { 36 | using (var client = new HttpClient()) 37 | { 38 | var response = await client.PostAsJsonAsync(Constants.LogicAppCommandUrl, command); 39 | return response; 40 | } 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Bot/VSTF_RD_Bot/Controllers/LoginController.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Bot.Connector; 2 | using Microsoft.IdentityModel.Clients.ActiveDirectory; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Configuration; 6 | using System.Linq; 7 | using System.Net; 8 | using System.Net.Http; 9 | using System.Web; 10 | using System.Web.Http; 11 | using System.Web.Http.Results; 12 | using Newtonsoft.Json; 13 | using Newtonsoft.Json.Linq; 14 | 15 | namespace VSTF_RD_Bot.Controllers 16 | { 17 | public class LoginController : ApiController 18 | { 19 | [HttpGet, Route("api/{userid}/login")] 20 | public RedirectResult Login(string userid) 21 | { 22 | return Redirect(String.Format("https://login.windows.net/common/oauth2/authorize?response_type=code&client_id={0}&redirect_uri={1}&resource={2}", 23 | Constants.ADClientId, HttpUtility.UrlEncode(Constants.apiBasePath + userid + "/authorize"), HttpUtility.UrlEncode("https://graph.windows.net/"))); 24 | } 25 | 26 | [HttpGet, Route("api/{userid}/authorize")] 27 | public async System.Threading.Tasks.Task Authorize(string userid, string code) 28 | { 29 | AuthenticationContext ac = new AuthenticationContext("https://login.windows.net/common/oauth2/authorize/"); 30 | ClientCredential cc = new ClientCredential(Constants.ADClientId, Constants.ADClientSecret); 31 | AuthenticationResult ar = await ac.AcquireTokenByAuthorizationCodeAsync(code, new Uri(Constants.apiBasePath + userid + "/authorize"), cc); 32 | if (!String.IsNullOrEmpty(ar.AccessToken)) 33 | { 34 | var client = new ConnectorClient(); 35 | var getData = await client.Bots.GetUserDataAsync(Constants.botId, userid); 36 | getData.Data = ar.Serialize(); 37 | var foo = await client.Bots.SetUserDataAsync(Constants.botId, userid, getData); 38 | 39 | //return Request.CreateResponse(foo); 40 | var response = Request.CreateResponse(HttpStatusCode.Moved); 41 | response.Headers.Location = new Uri("/loggedin.htm", UriKind.Relative); 42 | return response; 43 | 44 | 45 | } 46 | else 47 | return Request.CreateResponse(HttpStatusCode.Unauthorized); 48 | 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Bot/VSTF_RD_Bot/Controllers/MessagesController.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using System.Net.Http; 3 | using System.Threading.Tasks; 4 | using System.Web.Http; 5 | using Microsoft.Bot.Connector; 6 | using Microsoft.Bot.Connector.Utilities; 7 | using Microsoft.Bot.Builder.Dialogs; 8 | using VSTF_RD_Bot.Models; 9 | using System.Collections.Generic; 10 | using VSTF_RD_Bot.Controllers; 11 | using System; 12 | using Newtonsoft.Json; 13 | using Newtonsoft.Json.Linq; 14 | using System.Text.RegularExpressions; 15 | using Microsoft.IdentityModel.Clients.ActiveDirectory; 16 | 17 | namespace VSTF_RD_Bot 18 | { 19 | [BotAuthentication] 20 | public class MessagesController : ApiController 21 | { 22 | private ConnectorClient client = new ConnectorClient(); 23 | /// 24 | /// POST: api/Messages 25 | /// Receive a message from a user and reply to it 26 | /// 27 | public async Task Post([FromBody]Message message) 28 | { 29 | #region Check Authorization 30 | try 31 | { 32 | string d = (string)message.BotUserData; 33 | AuthenticationResult ar = AuthenticationResult.Deserialize(d); 34 | AuthenticationContext ac = new AuthenticationContext("https://login.windows.net/common/oauth2/authorize/"); 35 | ar = DateTimeOffset.Compare(DateTimeOffset.Now, ar.ExpiresOn) < 0 ? ar : await ac.AcquireTokenByRefreshTokenAsync(ar.RefreshToken, new ClientCredential(Constants.ADClientId, Constants.ADClientSecret)); 36 | } 37 | catch(Exception ex) 38 | { 39 | return message.CreateReplyMessage($"You must authenticate to use bot: https://jehollanVSBot.azurewebsites.net/api/{message.From.Id}/login"); 40 | } 41 | 42 | #endregion 43 | 44 | if (message.Type == "Message") 45 | { 46 | #region bot /commands 47 | if (Regex.IsMatch(message.Text, Constants.regex_command)) 48 | { 49 | string command = Regex.Match(message.Text, Constants.regex_command).Groups[1].Value; 50 | switch(command.ToLower()) 51 | { 52 | case "create": 53 | return createCommand(message); 54 | case "topfeatures": 55 | return logicAppCommand(message, "TopFeatures"); 56 | case "topbugs": 57 | return logicAppCommand(message, "TopBugs"); 58 | case "topcri": 59 | return logicAppCommand(message, "TopCRI"); 60 | case "currentsprint": 61 | return logicAppCommand(message, "CurrentSprint"); 62 | case "start": 63 | return message.CreateReplyMessage("Please welcome your bot overlord", "en"); 64 | case "logout": 65 | var getData = await client.Bots.GetUserDataAsync(Constants.botId, message.From.Id); 66 | getData.Data = null; 67 | await client.Bots.SetUserDataAsync(Constants.botId, message.From.Id, getData); 68 | return message.CreateReplyMessage("You have been logged out"); 69 | default: 70 | return message.CreateReplyMessage("Sorry, that's an invalid command", "en"); 71 | } 72 | 73 | } 74 | #endregion 75 | else 76 | { 77 | var reply = await Conversation.SendAsync(message, () => new VSTFDialog()); 78 | 79 | #region Check if I need to go start up a query or create 80 | var dialogQuery = reply.GetBotConversationData("userQuery"); 81 | var dialogCreate = reply.GetBotConversationData("userItem"); 82 | if (dialogQuery != null) 83 | { 84 | reply.SetBotConversationData("userQuery", null); 85 | Task.Factory.StartNew(async () => 86 | { 87 | await getQueryResults(message, dialogQuery); 88 | }); 89 | 90 | } 91 | else if (dialogCreate != null) 92 | { 93 | reply.SetBotConversationData("userItem", null); 94 | Task.Factory.StartNew(() => 95 | { 96 | createTFSItem(message, dialogCreate); 97 | }); 98 | } 99 | 100 | #endregion 101 | 102 | return reply; 103 | } 104 | 105 | } 106 | else 107 | { 108 | return HandleSystemMessage(message); 109 | } 110 | } 111 | 112 | /// 113 | /// Executing a command will trigger a Logic App which will read the blob specified and execute the query, returning results 114 | /// 115 | /// 116 | /// 117 | /// 118 | private Message logicAppCommand(Message message, string blobName) 119 | { 120 | string reply = $"Executing query..."; 121 | Task.Factory.StartNew(() => 122 | { 123 | fetchCommand(message, new Command() { blobName = blobName }); 124 | }); 125 | return message.CreateReplyMessage(reply, "en"); 126 | } 127 | 128 | private async void fetchCommand(Message message, Command command) 129 | { 130 | var response = await new LogicAppController().ExecuteCommand(command); 131 | IEnumerable items = await response.Content.ReadAsAsync>(); 132 | if (items.Count() == 0) 133 | client.Messages.SendMessage(message.CreateReplyMessage("No results found")); 134 | string text = ""; 135 | foreach (var item in items) 136 | { 137 | text += $"{item.id}: {item.Title}\n\n"; 138 | } 139 | var reply = message.CreateReplyMessage(text, "en"); 140 | client.Messages.SendMessageAsync(reply); 141 | } 142 | 143 | private Message createCommand(Message message) 144 | { 145 | string type, title, text; 146 | text = message.Text; 147 | 148 | var match = System.Text.RegularExpressions.Regex.Match(text, Constants.regex_create); 149 | type = match.Groups[1].Value; 150 | title = match.Groups[2].Value; 151 | 152 | string reply = $"Creating new {type} with title {title}"; 153 | var dialogCreate = new TFSItem() { title = title, type = type }; 154 | Task.Factory.StartNew(() => 155 | { 156 | createTFSItem(message, dialogCreate); 157 | }); 158 | 159 | 160 | return message.CreateReplyMessage(reply, "en"); 161 | } 162 | 163 | private async void createTFSItem(Message message, TFSItem dialogCreate) 164 | { 165 | var response = await new LogicAppController().CreateVSTF(dialogCreate); 166 | string itemId = (string)JObject.Parse(await response.Content.ReadAsStringAsync())["id"]; 167 | await client.Messages.SendMessageAsync(message.CreateReplyMessage($"Created item {itemId}", "en")); 168 | } 169 | 170 | private async Task getQueryResults(Message message, QueryItem queryItem) 171 | { 172 | var response = await new LogicAppController().SearchVSTF(queryItem); 173 | IEnumerable items = await response.Content.ReadAsAsync>(); 174 | if (items.Count() == 0) 175 | client.Messages.SendMessage(message.CreateReplyMessage("No results found")); 176 | foreach (var item in items) 177 | { 178 | string text = $"{item.id}: {item.Title}"; 179 | var reply = message.CreateReplyMessage(text, "en"); 180 | client.Messages.SendMessageAsync(reply); 181 | 182 | } 183 | 184 | 185 | 186 | } 187 | 188 | private Message HandleSystemMessage(Message message) 189 | { 190 | if (message.Type == "Ping") 191 | { 192 | Message reply = message.CreateReplyMessage(); 193 | reply.Type = "Ping"; 194 | return reply; 195 | } 196 | else if (message.Type == "DeleteUserData") 197 | { 198 | // Implement user deletion here 199 | // If we handle user deletion, return a real message 200 | } 201 | else if (message.Type == "BotAddedToConversation") 202 | { 203 | } 204 | else if (message.Type == "BotRemovedFromConversation") 205 | { 206 | } 207 | else if (message.Type == "UserAddedToConversation") 208 | { 209 | } 210 | else if (message.Type == "UserRemovedFromConversation") 211 | { 212 | } 213 | else if (message.Type == "EndOfConversation") 214 | { 215 | } 216 | 217 | return null; 218 | } 219 | } 220 | } -------------------------------------------------------------------------------- /Bot/VSTF_RD_Bot/DIalog/VSTFDialog.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Bot.Builder.Dialogs; 2 | using Microsoft.Bot.Builder.Luis; 3 | using Microsoft.Bot.Connector; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Threading.Tasks; 8 | using System.Web; 9 | using VSTF_RD_Bot.Controllers; 10 | using VSTF_RD_Bot.Models; 11 | using System.Net.Http; 12 | using System.Configuration; 13 | 14 | namespace VSTF_RD_Bot 15 | { 16 | [Serializable] 17 | [LuisModel(Constants.LUIS_AppId, Constants.LUIS_AppSecret)] 18 | public class VSTFDialog : LuisDialog 19 | { 20 | [LuisIntent("SearchVSTF")] 21 | public async Task searchVSTF(IDialogContext context, LuisResult result) 22 | { 23 | 24 | string query, type; 25 | if (TryFindType(result, out query, out type)) 26 | { 27 | string message = $"Searching for {query} in {type}...."; 28 | 29 | context.ConversationData.SetValue("userQuery", new QueryItem() { query = query, type = type }); 30 | 31 | await context.PostAsync(message); 32 | 33 | 34 | context.Wait(MessageReceived); 35 | 36 | } 37 | else if(query == null && type == null) 38 | { 39 | string message = $"I think you want to search, please try again.\n\n" + 40 | "Try a phrase like \"Search backlog for swagger\""; 41 | await context.PostAsync(message); 42 | context.Wait(MessageReceived); 43 | } 44 | else if(query == null) 45 | { 46 | string message = $"Ok, you want to search {type} - what should I search for?"; 47 | context.ConversationData.SetValue("type", type); 48 | await context.PostAsync(message); 49 | context.Wait(GetOtherField); 50 | } 51 | else 52 | { 53 | 54 | string message = $"Ok, you want to search for items about {query} - what item type?"; 55 | context.ConversationData.SetValue("query", query); 56 | await context.PostAsync(message); 57 | context.Wait(GetOtherField); 58 | 59 | } 60 | 61 | } 62 | 63 | [LuisIntent("AddVSTF")] 64 | public async Task addVSTF(IDialogContext context, LuisResult result) 65 | { 66 | string title, type; 67 | if (TryFindType(result, out title, out type)) 68 | { 69 | string message = $"Creating new {type} with title {title}"; 70 | 71 | new LogicAppController().CreateVSTF(new TFSItem() { title = title, type = type }); 72 | 73 | await context.PostAsync(message); 74 | context.Wait(MessageReceived); 75 | } 76 | else 77 | { 78 | string message = $"I think you want to create an item but didn't catch the title or type.\n\nTry: \"/create : \""; 79 | await context.PostAsync(message); 80 | context.Wait(MessageReceived); 81 | } 82 | 83 | } 84 | 85 | [LuisIntent("")] 86 | public async Task noIntent(IDialogContext context, LuisResult result) 87 | { 88 | string text = "Sorry, didn't understand. Try again"; 89 | 90 | await context.PostAsync(text); 91 | context.Wait(MessageReceived); 92 | } 93 | 94 | public async Task GetOtherField(IDialogContext context, IAwaitable<Message> argument) 95 | { 96 | var incomingMessage = await argument; 97 | string type = null; 98 | string query = null; 99 | if (context.ConversationData.TryGetValue("type", out type)) 100 | query = incomingMessage.Text; 101 | else if (context.ConversationData.TryGetValue("query", out query)) 102 | type = incomingMessage.Text; 103 | //var searching = context.MakeMessage().CreateReplyMessage(, "en"); 104 | //await connector.Messages.SendMessageAsync(searching); 105 | string message = $"Searching for {query} in {type}...."; 106 | 107 | context.ConversationData.SetValue<QueryItem>("userQuery", new QueryItem() { query = query, type = type }); 108 | 109 | await context.PostAsync(message); 110 | context.Wait(MessageReceived); 111 | 112 | } 113 | 114 | private bool TryFindType(LuisResult result, out string query, out string type) 115 | { 116 | query = null; 117 | type = null; 118 | 119 | EntityRecommendation QueryEntity, TitleEntity, TypeEntity; 120 | if (result.TryFindEntity(Constants.Query_Entity, out QueryEntity)) 121 | query = QueryEntity.Entity; 122 | 123 | if (result.TryFindEntity(Constants.Title_Entity, out TitleEntity)) 124 | query = TitleEntity.Entity; 125 | 126 | if (result.TryFindEntity(Constants.Type_Entity, out TypeEntity)) 127 | type = TypeEntity.Entity; 128 | 129 | if (query != null && type != null) 130 | return true; 131 | 132 | return false; 133 | } 134 | } 135 | 136 | } -------------------------------------------------------------------------------- /Bot/VSTF_RD_Bot/Global.asax: -------------------------------------------------------------------------------- 1 | <%@ Application Codebehind="Global.asax.cs" Inherits="VSTF_RD_Bot.WebApiApplication" Language="C#" %> 2 | -------------------------------------------------------------------------------- /Bot/VSTF_RD_Bot/Global.asax.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.Http; 6 | using System.Web.Routing; 7 | 8 | namespace VSTF_RD_Bot 9 | { 10 | public class WebApiApplication : System.Web.HttpApplication 11 | { 12 | protected void Application_Start() 13 | { 14 | GlobalConfiguration.Configure(WebApiConfig.Register); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Bot/VSTF_RD_Bot/Models/Command.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | 6 | namespace VSTF_RD_Bot.Models 7 | { 8 | public class Command 9 | { 10 | public string blobName { get; set; } 11 | } 12 | } -------------------------------------------------------------------------------- /Bot/VSTF_RD_Bot/Models/QueryItem.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | 6 | namespace VSTF_RD_Bot.Models 7 | { 8 | public class QueryItem 9 | { 10 | public string type { get; set; } 11 | public string query { get; set; } 12 | } 13 | } -------------------------------------------------------------------------------- /Bot/VSTF_RD_Bot/Models/TFSItem.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | 6 | namespace VSTF_RD_Bot.Models 7 | { 8 | public class TFSItem 9 | { 10 | public string title { get; set; } 11 | public string type { get; set; } 12 | } 13 | } -------------------------------------------------------------------------------- /Bot/VSTF_RD_Bot/Models/TFSResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | 6 | namespace VSTF_RD_Bot.Models 7 | { 8 | public class TFSResponse 9 | { 10 | public string Type { get; set; } 11 | public string Title { get; set; } 12 | public string AreaPath { get; set; } 13 | public string State { get; set; } 14 | public string IterationPath { get; set; } 15 | public string LinkType { get; set; } 16 | public int LinkId { get; set; } 17 | 18 | public int id { get; set; } 19 | } 20 | } -------------------------------------------------------------------------------- /Bot/VSTF_RD_Bot/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("VSTF_RD_Bot")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("VSTF_RD_Bot")] 13 | [assembly: AssemblyCopyright("Copyright © 2015")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("a8ba1066-5695-4d71-abb4-65e5a5e0c3d4")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Revision and Build Numbers 33 | // by using the '*' as shown below: 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /Bot/VSTF_RD_Bot/VSTF_RD_Bot.csproj: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="utf-8"?> 2 | <Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> 3 | <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> 4 | <PropertyGroup> 5 | <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> 6 | <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> 7 | <ProductVersion> 8 | </ProductVersion> 9 | <SchemaVersion>2.0</SchemaVersion> 10 | <ProjectGuid>{A8BA1066-5695-4D71-ABB4-65E5A5E0C3D4}</ProjectGuid> 11 | <ProjectTypeGuids>{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids> 12 | <OutputType>Library</OutputType> 13 | <AppDesignerFolder>Properties</AppDesignerFolder> 14 | <RootNamespace>VSTF_RD_Bot</RootNamespace> 15 | <AssemblyName>VSTF_RD_Bot</AssemblyName> 16 | <TargetFrameworkVersion>v4.6</TargetFrameworkVersion> 17 | <UseIISExpress>true</UseIISExpress> 18 | <IISExpressSSLPort /> 19 | <IISExpressAnonymousAuthentication /> 20 | <IISExpressWindowsAuthentication /> 21 | <IISExpressUseClassicPipelineMode /> 22 | <UseGlobalApplicationHostFile /> 23 | <NuGetPackageImportStamp> 24 | </NuGetPackageImportStamp> 25 | <TargetFrameworkProfile /> 26 | </PropertyGroup> 27 | <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> 28 | <DebugSymbols>true</DebugSymbols> 29 | <DebugType>full</DebugType> 30 | <Optimize>false</Optimize> 31 | <OutputPath>bin\</OutputPath> 32 | <DefineConstants>DEBUG;TRACE</DefineConstants> 33 | <ErrorReport>prompt</ErrorReport> 34 | <WarningLevel>4</WarningLevel> 35 | </PropertyGroup> 36 | <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> 37 | <DebugType>pdbonly</DebugType> 38 | <Optimize>true</Optimize> 39 | <OutputPath>bin\</OutputPath> 40 | <DefineConstants>TRACE</DefineConstants> 41 | <ErrorReport>prompt</ErrorReport> 42 | <WarningLevel>4</WarningLevel> 43 | </PropertyGroup> 44 | <ItemGroup> 45 | <Reference Include="Microsoft.Bot.Builder, Version=1.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> 46 | <HintPath>..\packages\Microsoft.Bot.Builder.1.0.1.0\lib\net45\Microsoft.Bot.Builder.dll</HintPath> 47 | <Private>True</Private> 48 | </Reference> 49 | <Reference Include="Microsoft.Bot.Connector, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> 50 | <HintPath>..\packages\Microsoft.Bot.Connector.1.0.0.0\lib\net45\Microsoft.Bot.Connector.dll</HintPath> 51 | <Private>True</Private> 52 | </Reference> 53 | <Reference Include="Microsoft.Bot.Connector.Utilities, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> 54 | <HintPath>..\packages\Microsoft.Bot.Connector.1.0.0.0\lib\net45\Microsoft.Bot.Connector.Utilities.dll</HintPath> 55 | <Private>True</Private> 56 | </Reference> 57 | <Reference Include="Microsoft.CSharp" /> 58 | <Reference Include="Microsoft.IdentityModel.Clients.ActiveDirectory, Version=2.23.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> 59 | <HintPath>..\packages\Microsoft.IdentityModel.Clients.ActiveDirectory.2.23.302261847\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.dll</HintPath> 60 | <Private>True</Private> 61 | </Reference> 62 | <Reference Include="Microsoft.IdentityModel.Clients.ActiveDirectory.WindowsForms, Version=2.23.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> 63 | <HintPath>..\packages\Microsoft.IdentityModel.Clients.ActiveDirectory.2.23.302261847\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.WindowsForms.dll</HintPath> 64 | <Private>True</Private> 65 | </Reference> 66 | <Reference Include="Microsoft.Rest.ClientRuntime, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> 67 | <HintPath>..\packages\Microsoft.Rest.ClientRuntime.1.8.2\lib\net45\Microsoft.Rest.ClientRuntime.dll</HintPath> 68 | <Private>True</Private> 69 | </Reference> 70 | <Reference Include="Microsoft.WindowsAzure.Configuration, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> 71 | <HintPath>..\packages\Microsoft.WindowsAzure.ConfigurationManager.3.1.0\lib\net40\Microsoft.WindowsAzure.Configuration.dll</HintPath> 72 | <Private>True</Private> 73 | </Reference> 74 | <Reference Include="Newtonsoft.Json, Version=8.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL"> 75 | <HintPath>..\packages\Newtonsoft.Json.8.0.2\lib\net45\Newtonsoft.Json.dll</HintPath> 76 | <Private>True</Private> 77 | </Reference> 78 | <Reference Include="System.Data.DataSetExtensions" /> 79 | <Reference Include="System.Net" /> 80 | <Reference Include="System.Net.Http" /> 81 | <Reference Include="System.Net.Http.Formatting, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> 82 | <HintPath>..\packages\Microsoft.AspNet.WebApi.Client.5.2.3\lib\net45\System.Net.Http.Formatting.dll</HintPath> 83 | <Private>True</Private> 84 | </Reference> 85 | <Reference Include="System.Net.Http.WebRequest" /> 86 | <Reference Include="System.Web.DynamicData" /> 87 | <Reference Include="System.Web.Entity" /> 88 | <Reference Include="System.Web.ApplicationServices" /> 89 | <Reference Include="System.ComponentModel.DataAnnotations" /> 90 | <Reference Include="System" /> 91 | <Reference Include="System.Data" /> 92 | <Reference Include="System.Web.Extensions" /> 93 | <Reference Include="System.Drawing" /> 94 | <Reference Include="System.Web" /> 95 | <Reference Include="System.Web.Http, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> 96 | <HintPath>..\packages\Microsoft.AspNet.WebApi.Core.5.2.3\lib\net45\System.Web.Http.dll</HintPath> 97 | <Private>True</Private> 98 | </Reference> 99 | <Reference Include="System.Web.Http.WebHost, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> 100 | <HintPath>..\packages\Microsoft.AspNet.WebApi.WebHost.5.2.3\lib\net45\System.Web.Http.WebHost.dll</HintPath> 101 | <Private>True</Private> 102 | </Reference> 103 | <Reference Include="System.Xml" /> 104 | <Reference Include="System.Configuration" /> 105 | <Reference Include="System.Web.Services" /> 106 | <Reference Include="System.EnterpriseServices" /> 107 | <Reference Include="System.Xml.Linq" /> 108 | </ItemGroup> 109 | <ItemGroup> 110 | <Content Include="default.htm" /> 111 | <Content Include="loggedin.htm" /> 112 | <Content Include="Global.asax" /> 113 | <Content Include="Web.config" /> 114 | </ItemGroup> 115 | <ItemGroup> 116 | <Compile Include="App_Start\WebApiConfig.cs" /> 117 | <Compile Include="Constants\Constants.cs" /> 118 | <Compile Include="Controllers\LogicAppController.cs" /> 119 | <Compile Include="Controllers\LoginController.cs" /> 120 | <Compile Include="Controllers\MessagesController.cs" /> 121 | <Compile Include="DIalog\VSTFDialog.cs" /> 122 | <Compile Include="Global.asax.cs"> 123 | <DependentUpon>Global.asax</DependentUpon> 124 | </Compile> 125 | <Compile Include="Models\Command.cs" /> 126 | <Compile Include="Models\QueryItem.cs" /> 127 | <Compile Include="Models\TFSItem.cs" /> 128 | <Compile Include="Models\TFSResponse.cs" /> 129 | <Compile Include="Properties\AssemblyInfo.cs" /> 130 | </ItemGroup> 131 | <ItemGroup> 132 | <Content Include="packages.config" /> 133 | <None Include="Properties\PublishProfiles\jehollanVSBot - Web Deploy.pubxml" /> 134 | <None Include="Web.Debug.config"> 135 | <DependentUpon>Web.config</DependentUpon> 136 | </None> 137 | <None Include="Web.Release.config"> 138 | <DependentUpon>Web.config</DependentUpon> 139 | </None> 140 | </ItemGroup> 141 | <ItemGroup /> 142 | <PropertyGroup> 143 | <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion> 144 | <VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath> 145 | </PropertyGroup> 146 | <PropertyGroup> 147 | <EnableMSDeployAppOffline>true</EnableMSDeployAppOffline> 148 | </PropertyGroup> 149 | <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> 150 | <Import Project="$(VSToolsPath)\WebApplications\Microsoft.WebApplication.targets" Condition="'$(VSToolsPath)' != ''" /> 151 | <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" Condition="false" /> 152 | <ProjectExtensions> 153 | <VisualStudio> 154 | <FlavorProperties GUID="{349c5851-65df-11da-9384-00065b846f21}"> 155 | <WebProjectProperties> 156 | <UseIIS>True</UseIIS> 157 | <AutoAssignPort>True</AutoAssignPort> 158 | <DevelopmentServerPort>3978</DevelopmentServerPort> 159 | <DevelopmentServerVPath>/</DevelopmentServerVPath> 160 | <IISUrl>http://localhost:3978/</IISUrl> 161 | <NTLMAuthentication>False</NTLMAuthentication> 162 | <UseCustomServer>False</UseCustomServer> 163 | <CustomServerUrl> 164 | </CustomServerUrl> 165 | <SaveServerSettingsInUserFile>False</SaveServerSettingsInUserFile> 166 | </WebProjectProperties> 167 | </FlavorProperties> 168 | </VisualStudio> 169 | </ProjectExtensions> 170 | <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 171 | Other similar extension points exist, see Microsoft.Common.targets. 172 | <Target Name="BeforeBuild"> 173 | </Target> 174 | <Target Name="AfterBuild"> 175 | </Target> 176 | --> 177 | </Project> -------------------------------------------------------------------------------- /Bot/VSTF_RD_Bot/Web.Debug.config: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="utf-8"?> 2 | 3 | <!-- For more information on using web.config transformation visit http://go.microsoft.com/fwlink/?LinkId=125889 --> 4 | 5 | <configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform"> 6 | <!-- 7 | In the example below, the "SetAttributes" transform will change the value of 8 | "connectionString" to use "ReleaseSQLServer" only when the "Match" locator 9 | finds an attribute "name" that has a value of "MyDB". 10 | 11 | <connectionStrings> 12 | <add name="MyDB" 13 | connectionString="Data Source=ReleaseSQLServer;Initial Catalog=MyReleaseDB;Integrated Security=True" 14 | xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/> 15 | </connectionStrings> 16 | --> 17 | <system.web> 18 | <!-- 19 | In the example below, the "Replace" transform will replace the entire 20 | <customErrors> section of your web.config file. 21 | Note that because there is only one customErrors section under the 22 | <system.web> node, there is no need to use the "xdt:Locator" attribute. 23 | 24 | <customErrors defaultRedirect="GenericError.htm" 25 | mode="RemoteOnly" xdt:Transform="Replace"> 26 | <error statusCode="500" redirect="InternalError.htm"/> 27 | </customErrors> 28 | --> 29 | </system.web> 30 | </configuration> -------------------------------------------------------------------------------- /Bot/VSTF_RD_Bot/Web.Release.config: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="utf-8"?> 2 | 3 | <!-- For more information on using web.config transformation visit http://go.microsoft.com/fwlink/?LinkId=125889 --> 4 | 5 | <configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform"> 6 | <!-- 7 | In the example below, the "SetAttributes" transform will change the value of 8 | "connectionString" to use "ReleaseSQLServer" only when the "Match" locator 9 | finds an attribute "name" that has a value of "MyDB". 10 | 11 | <connectionStrings> 12 | <add name="MyDB" 13 | connectionString="Data Source=ReleaseSQLServer;Initial Catalog=MyReleaseDB;Integrated Security=True" 14 | xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/> 15 | </connectionStrings> 16 | --> 17 | <system.web> 18 | <compilation xdt:Transform="RemoveAttributes(debug)" /> 19 | <!-- 20 | In the example below, the "Replace" transform will replace the entire 21 | <customErrors> section of your web.config file. 22 | Note that because there is only one customErrors section under the 23 | <system.web> node, there is no need to use the "xdt:Locator" attribute. 24 | 25 | <customErrors defaultRedirect="GenericError.htm" 26 | mode="RemoteOnly" xdt:Transform="Replace"> 27 | <error statusCode="500" redirect="InternalError.htm"/> 28 | </customErrors> 29 | --> 30 | </system.web> 31 | </configuration> -------------------------------------------------------------------------------- /Bot/VSTF_RD_Bot/Web.config: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="utf-8"?> 2 | <!-- 3 | For more information on how to configure your ASP.NET application, please visit 4 | http://go.microsoft.com/fwlink/?LinkId=301879 5 | --> 6 | <configuration> 7 | <appSettings> 8 | <!-- update these with your appid and one of your appsecret keys--> 9 | <add key="AppId" value="YourAppId" /> 10 | <add key="AppSecret" value="YourAppSecret" /> 11 | <add key="ADClientId" value="AD Client ID" /> 12 | <add key="ADClientSecret" value="AD Client Secrent" /> 13 | <add key="logicAppQueryUrl" value="Manual Trigger URL Goes Here"/> 14 | <add key="logicAppCreateUrl" value="Manual Trigger URL Goes Here"/> 15 | <add key="logicAppCommandUrl" value="Manual Trigger URL Goes Here"/> 16 | <add key="apiBasePath" value="(my azure website).net/api/"/> 17 | </appSettings> 18 | <!-- 19 | For a description of web.config changes see http://go.microsoft.com/fwlink/?LinkId=235367. 20 | 21 | The following attributes can be set on the <httpRuntime> tag. 22 | <system.Web> 23 | <httpRuntime targetFramework="4.6" /> 24 | </system.Web> 25 | --> 26 | <system.web> 27 | <customErrors mode="Off" /> 28 | <compilation debug="true" targetFramework="4.6" /> 29 | <httpRuntime targetFramework="4.6" /> 30 | </system.web> 31 | <system.webServer> 32 | <defaultDocument> 33 | <files> 34 | <clear /> 35 | <add value="default.htm" /> 36 | </files> 37 | </defaultDocument> 38 | 39 | <handlers> 40 | <remove name="ExtensionlessUrlHandler-Integrated-4.0" /> 41 | <remove name="OPTIONSVerbHandler" /> 42 | <remove name="TRACEVerbHandler" /> 43 | <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" /> 44 | </handlers></system.webServer> 45 | <runtime> 46 | <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> 47 | <dependentAssembly> 48 | <assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" /> 49 | <bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0" /> 50 | </dependentAssembly> 51 | <dependentAssembly> 52 | <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" /> 53 | <bindingRedirect oldVersion="1.0.0.0-5.2.3.0" newVersion="5.2.3.0" /> 54 | </dependentAssembly> 55 | <dependentAssembly> 56 | <assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" /> 57 | <bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0" /> 58 | </dependentAssembly> 59 | <dependentAssembly> 60 | <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" /> 61 | <bindingRedirect oldVersion="0.0.0.0-8.0.0.0" newVersion="8.0.0.0" /> 62 | </dependentAssembly> 63 | <dependentAssembly> 64 | <assemblyIdentity name="System.Net.Http.Primitives" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" /> 65 | <bindingRedirect oldVersion="0.0.0.0-4.2.29.0" newVersion="4.2.29.0" /> 66 | </dependentAssembly> 67 | <dependentAssembly> 68 | <assemblyIdentity name="System.Net.Http.Formatting" publicKeyToken="31bf3856ad364e35" culture="neutral" /> 69 | <bindingRedirect oldVersion="0.0.0.0-5.2.3.0" newVersion="5.2.3.0" /> 70 | </dependentAssembly> 71 | </assemblyBinding> 72 | </runtime> 73 | </configuration> -------------------------------------------------------------------------------- /Bot/VSTF_RD_Bot/default.htm: -------------------------------------------------------------------------------- 1 | <!DOCTYPE html> 2 | <html> 3 | <head> 4 | <title> 5 | 6 | 7 | 8 |

VSTF_RD_Bot

9 |

Describe your bot here and your terms of use etc.

10 |

Visit Bot Framework to register your bot. When you register it, remember to set your bot's endpoint to

https://your_bots_hostname/api/messages

11 | 12 | 13 | -------------------------------------------------------------------------------- /Bot/VSTF_RD_Bot/loggedin.htm: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Logic Apps VS Bot 5 | 6 | 7 | 8 |

Successfully Authenticated

9 |

You can now chat with the bot.

10 | 11 | 12 | -------------------------------------------------------------------------------- /Bot/VSTF_RD_Bot/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Jeff Hollan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Logic_Apps/Bot_Create_VSTF.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", 3 | "contentVersion": "1.0.0.0", 4 | "parameters": { 5 | "logicAppName": { 6 | "type": "string", 7 | "defaultValue": "Bot_VSTF_Create" 8 | }, 9 | "svcPlanName": { 10 | "type": "string", 11 | "metadata": { 12 | "description": "The name of the App Service plan to create for hosting the logic app." 13 | } 14 | }, 15 | "sku": { 16 | "type": "string", 17 | "defaultValue": "Standard", 18 | "allowedValues": [ 19 | "Free", 20 | "Basic", 21 | "Standard", 22 | "Premium" 23 | ], 24 | "metadata": { 25 | "description": "The pricing tier for the logic app." 26 | } 27 | }, 28 | "svcPlanSize": { 29 | "defaultValue": "0", 30 | "type": "string", 31 | "allowedValues": [ 32 | "0", 33 | "1", 34 | "2" 35 | ], 36 | "metadata": { 37 | "description": "The instance size of the app." 38 | } 39 | } 40 | }, 41 | "variables": {}, 42 | "resources": [ 43 | { 44 | "apiVersion": "2014-06-01", 45 | "name": "[parameters('svcPlanName')]", 46 | "type": "Microsoft.Web/serverfarms", 47 | "location": "[resourceGroup().location]", 48 | "tags": { 49 | "displayName": "AppServicePlan" 50 | }, 51 | "properties": { 52 | "name": "[parameters('svcPlanName')]", 53 | "sku": "[parameters('sku')]", 54 | "workerSize": "[parameters('svcPlanSize')]", 55 | "numberOfWorkers": 1 56 | } 57 | }, 58 | { 59 | "type": "Microsoft.Logic/workflows", 60 | "apiVersion": "2015-02-01-preview", 61 | "name": "[parameters('logicAppName')]", 62 | "location": "[resourceGroup().location]", 63 | "tags": { 64 | "displayName": "LogicApp" 65 | }, 66 | "properties": { 67 | "sku": { 68 | "name": "[parameters('sku')]", 69 | "plan": { 70 | "id": "[concat(resourceGroup().id, '/providers/Microsoft.Web/serverfarms/',parameters('svcPlanName'))]" 71 | } 72 | }, 73 | "definition": { 74 | "$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2015-08-01-preview/workflowdefinition.json#", 75 | "actions": { 76 | "CreateNewItem": { 77 | "conditions": [ 78 | { 79 | "expression": "@equals(triggerBody()['type'], 'bug')" 80 | } 81 | ], 82 | "inputs": { 83 | "body": { 84 | "AreaPath": "My Area Path", 85 | "AssignedTo": "Jeff Hollan", 86 | "HowFound": "Customer", 87 | "IterationPath": "My Iteration Path", 88 | "LinkId": 1234567, 89 | "LinkType": "Parent", 90 | "Priority": 1, 91 | "State": "Active", 92 | "Title": "@{triggerBody()['title']}", 93 | "Type": "Bug" 94 | }, 95 | "method": "post", 96 | "queries": { 97 | "requestedCollectionUri": "http://myvisualstudioteamfoundation", 98 | "requestedProject": "My Project" 99 | }, 100 | "uri": "https://myvsapi.azurewebsites.net/api/tfs/create" 101 | }, 102 | "metadata": { 103 | "apiDefinitionUrl": "https://myvsapi.azurewebsites.net/swagger/docs/v1", 104 | "swaggerSource": "website" 105 | }, 106 | "type": "Http" 107 | }, 108 | "CreateNewItem_2": { 109 | "conditions": [ 110 | { 111 | "expression": "@equals(actions('CreateNewItem').status, 'Skipped')" 112 | } 113 | ], 114 | "inputs": { 115 | "body": { 116 | "AreaPath": "My Area Path", 117 | "IterationPath": "My Iteration Path", 118 | "LinkId": 1234567, 119 | "LinkType": "Parent", 120 | "State": "New", 121 | "Title": "@{triggerBody()['title']}", 122 | "Type": "Product Backlog Item" 123 | }, 124 | "method": "post", 125 | "queries": { 126 | "requestedCollectionUri": "http://myvisualstudioteamfoundation", 127 | "requestedProject": "My Project" 128 | }, 129 | "uri": "https://myvsapi.azurewebsites.net/api/tfs/create" 130 | }, 131 | "metadata": { 132 | "apiDefinitionUrl": "https://myvsapi.azurewebsites.net/swagger/docs/v1", 133 | "swaggerSource": "website" 134 | }, 135 | "type": "Http" 136 | }, 137 | "Response": { 138 | "conditions": [ 139 | { 140 | "dependsOn": "CreateNewItem" 141 | } 142 | ], 143 | "inputs": { 144 | "body": { 145 | "id": "@{body('CreateNewItem')['id']}" 146 | }, 147 | "headers": { 148 | "content-type": "application/json" 149 | }, 150 | "statusCode": 200 151 | }, 152 | "type": "Response" 153 | }, 154 | "Response_2": { 155 | "conditions": [ 156 | { 157 | "dependsOn": "CreateNewItem_2" 158 | } 159 | ], 160 | "inputs": { 161 | "body": { 162 | "id": "@{body('CreateNewItem_2')['id']}" 163 | }, 164 | "headers": { 165 | "content-type": "application/json" 166 | }, 167 | "statusCode": 200 168 | }, 169 | "type": "Response" 170 | } 171 | }, 172 | "contentVersion": "1.0.0.0", 173 | "outputs": {}, 174 | "parameters": {}, 175 | "triggers": { 176 | "manual": { 177 | "inputs": { 178 | "schema": { 179 | "properties": { 180 | "title": { 181 | "id": "http://jsonschema.net/title", 182 | "type": "string" 183 | }, 184 | "type": { 185 | "id": "http://jsonschema.net/type", 186 | "type": "string" 187 | } 188 | }, 189 | "required": [ 190 | "title", 191 | "type" 192 | ], 193 | "type": "object" 194 | } 195 | }, 196 | "type": "Manual" 197 | } 198 | } 199 | }, 200 | "parameters": {} 201 | } 202 | } 203 | ], 204 | "outputs": {} 205 | } -------------------------------------------------------------------------------- /Logic_Apps/Bot_ExecuteCommand_VSTF.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", 3 | "contentVersion": "1.0.0.0", 4 | "parameters": { 5 | "logicAppName": { 6 | "type": "string", 7 | "defaultValue": "Bot_VSTF_Create" 8 | }, 9 | "svcPlanName": { 10 | "type": "string", 11 | "metadata": { 12 | "description": "The name of the App Service plan to create for hosting the logic app." 13 | } 14 | }, 15 | "sku": { 16 | "type": "string", 17 | "defaultValue": "Standard", 18 | "allowedValues": [ 19 | "Free", 20 | "Basic", 21 | "Standard", 22 | "Premium" 23 | ], 24 | "metadata": { 25 | "description": "The pricing tier for the logic app." 26 | } 27 | }, 28 | "svcPlanSize": { 29 | "defaultValue": "0", 30 | "type": "string", 31 | "allowedValues": [ 32 | "0", 33 | "1", 34 | "2" 35 | ], 36 | "metadata": { 37 | "description": "The instance size of the app." 38 | } 39 | } 40 | }, 41 | "variables": {}, 42 | "resources": [ 43 | { 44 | "apiVersion": "2014-06-01", 45 | "name": "[parameters('svcPlanName')]", 46 | "type": "Microsoft.Web/serverfarms", 47 | "location": "[resourceGroup().location]", 48 | "tags": { 49 | "displayName": "AppServicePlan" 50 | }, 51 | "properties": { 52 | "name": "[parameters('svcPlanName')]", 53 | "sku": "[parameters('sku')]", 54 | "workerSize": "[parameters('svcPlanSize')]", 55 | "numberOfWorkers": 1 56 | } 57 | }, 58 | { 59 | "type": "Microsoft.Logic/workflows", 60 | "apiVersion": "2015-02-01-preview", 61 | "name": "[parameters('logicAppName')]", 62 | "location": "[resourceGroup().location]", 63 | "tags": { 64 | "displayName": "LogicApp" 65 | }, 66 | "properties": { 67 | "sku": { 68 | "name": "[parameters('sku')]", 69 | "plan": { 70 | "id": "[concat(resourceGroup().id, '/providers/Microsoft.Web/serverfarms/',parameters('svcPlanName'))]" 71 | } 72 | }, 73 | "definition": { 74 | "$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2015-08-01-preview/workflowdefinition.json#", 75 | "actions": { 76 | "ExecuteQuery_getTopItems": { 77 | "conditions": [ 78 | { 79 | "dependsOn": "Get_file_content_using_path" 80 | } 81 | ], 82 | "inputs": { 83 | "method": "get", 84 | "queries": { 85 | "count": 10, 86 | "query": "@{body('Get_file_content_using_path')}", 87 | "requestedCollectionUri": "http://myvisualstudioteamfoundation", 88 | "requestedProject": "My Project" 89 | }, 90 | "uri": "https://myvsapi.azurewebsites.net/api/ExecuteQuery" 91 | }, 92 | "metadata": { 93 | "apiDefinitionUrl": "https://myvsapi.azurewebsites.net/swagger/docs/v1", 94 | "swaggerSource": "website" 95 | }, 96 | "type": "Http" 97 | }, 98 | "Get_file_content_using_path": { 99 | "conditions": [], 100 | "inputs": { 101 | "host": { 102 | "api": { 103 | "runtimeUrl": "https://logic-apis-eastus.azure-apim.net/apim/azureblob" 104 | }, 105 | "connection": { 106 | "name": "@parameters('$connections')['azureblob']['connectionId']" 107 | } 108 | }, 109 | "method": "get", 110 | "path": "/datasets/default/GetFileContentByPath", 111 | "queries": { 112 | "path": "/logicapps/@{triggerBody()['blobName']}" 113 | } 114 | }, 115 | "type": "ApiConnection" 116 | }, 117 | "Response": { 118 | "conditions": [ 119 | { 120 | "dependsOn": "ExecuteQuery_getTopItems" 121 | } 122 | ], 123 | "inputs": { 124 | "body": "@body('ExecuteQuery_getTopItems')", 125 | "headers": { 126 | "Content-Type": "application/json" 127 | }, 128 | "statusCode": 200 129 | }, 130 | "type": "Response" 131 | } 132 | }, 133 | "contentVersion": "1.0.0.0", 134 | "outputs": {}, 135 | "parameters": { 136 | "$connections": { 137 | "defaultValue": {}, 138 | "type": "Object" 139 | } 140 | }, 141 | "triggers": { 142 | "manual": { 143 | "inputs": { 144 | "schema": { 145 | "properties": { 146 | "blobName": { 147 | "id": "blobName", 148 | "type": "string" 149 | } 150 | }, 151 | "required": [ 152 | "blobName" 153 | ], 154 | "type": "object" 155 | } 156 | }, 157 | "type": "Manual" 158 | } 159 | } 160 | }, 161 | "parameters": { 162 | "$connections": { 163 | "azureblob":{ 164 | "connectionId":"/some/connection/id" 165 | } 166 | } 167 | } 168 | } 169 | } 170 | ], 171 | "outputs": {} 172 | } -------------------------------------------------------------------------------- /Logic_Apps/Bot_Search_VSTF.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", 3 | "contentVersion": "1.0.0.0", 4 | "parameters": { 5 | "logicAppName": { 6 | "type": "string", 7 | "defaultValue": "Bot_VSTF_Create" 8 | }, 9 | "svcPlanName": { 10 | "type": "string", 11 | "metadata": { 12 | "description": "The name of the App Service plan to create for hosting the logic app." 13 | } 14 | }, 15 | "sku": { 16 | "type": "string", 17 | "defaultValue": "Standard", 18 | "allowedValues": [ 19 | "Free", 20 | "Basic", 21 | "Standard", 22 | "Premium" 23 | ], 24 | "metadata": { 25 | "description": "The pricing tier for the logic app." 26 | } 27 | }, 28 | "svcPlanSize": { 29 | "defaultValue": "0", 30 | "type": "string", 31 | "allowedValues": [ 32 | "0", 33 | "1", 34 | "2" 35 | ], 36 | "metadata": { 37 | "description": "The instance size of the app." 38 | } 39 | } 40 | }, 41 | "variables": {}, 42 | "resources": [ 43 | { 44 | "apiVersion": "2014-06-01", 45 | "name": "[parameters('svcPlanName')]", 46 | "type": "Microsoft.Web/serverfarms", 47 | "location": "[resourceGroup().location]", 48 | "tags": { 49 | "displayName": "AppServicePlan" 50 | }, 51 | "properties": { 52 | "name": "[parameters('svcPlanName')]", 53 | "sku": "[parameters('sku')]", 54 | "workerSize": "[parameters('svcPlanSize')]", 55 | "numberOfWorkers": 1 56 | } 57 | }, 58 | { 59 | "type": "Microsoft.Logic/workflows", 60 | "apiVersion": "2015-02-01-preview", 61 | "name": "[parameters('logicAppName')]", 62 | "location": "[resourceGroup().location]", 63 | "tags": { 64 | "displayName": "LogicApp" 65 | }, 66 | "properties": { 67 | "sku": { 68 | "name": "[parameters('sku')]", 69 | "plan": { 70 | "id": "[concat(resourceGroup().id, '/providers/Microsoft.Web/serverfarms/',parameters('svcPlanName'))]" 71 | } 72 | }, 73 | "definition": { 74 | "$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2015-08-01-preview/workflowdefinition.json#", 75 | "actions": { 76 | "Response": { 77 | "conditions": [ 78 | { 79 | "dependsOn": "SearchItem_SearchItem" 80 | } 81 | ], 82 | "inputs": { 83 | "body": "@body('SearchItem_SearchItem')", 84 | "headers": { 85 | "content-type": "application/json" 86 | }, 87 | "statusCode": 200 88 | }, 89 | "type": "Response" 90 | }, 91 | "SearchItem_SearchItem": { 92 | "conditions": [], 93 | "inputs": { 94 | "body": { 95 | "query": "@{triggerBody()['query']}", 96 | "type": "@{triggerBody()['type']}" 97 | }, 98 | "method": "post", 99 | "queries": { 100 | "count": 5, 101 | "requestedCollectionUri": "http://myvisualstudioteamfoundation", 102 | "requestedProject": "My Project" 103 | }, 104 | "uri": "https://myvsapi.azurewebsites.net/api/tfs/search" 105 | }, 106 | "metadata": { 107 | "apiDefinitionUrl": "https://myvsapi.azurewebsites.net/swagger/docs/v1", 108 | "swaggerSource": "website" 109 | }, 110 | "type": "Http" 111 | } 112 | }, 113 | "contentVersion": "1.0.0.0", 114 | "outputs": {}, 115 | "parameters": {}, 116 | "triggers": { 117 | "manual": { 118 | "inputs": { 119 | "schema": { 120 | "properties": { 121 | "query": { 122 | "id": "http://jsonschema.net/query", 123 | "type": "string" 124 | }, 125 | "type": { 126 | "id": "http://jsonschema.net/type", 127 | "type": "string" 128 | } 129 | }, 130 | "required": [ 131 | "query", 132 | "type" 133 | ], 134 | "type": "object" 135 | } 136 | }, 137 | "type": "Manual" 138 | } 139 | } 140 | }, 141 | "parameters": {} 142 | } 143 | } 144 | ], 145 | "outputs": {} 146 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # BotFrameworkSample 2 | 3 | Bot Framework project I completed that hosts a bot to interface with Visual Studio Team Services. Uses Logic Apps to complete the tasks, and Azure Directory Authentication 4 | 5 | ## How the different pieces interact ## 6 | 7 | ### Bot Host ### 8 | 9 | First I created the bot host. This is an Azure Web Site that accepts incoming requests from the Bot Framework, routes them to luis.ai, and then does some action based on the intent. For now the intents I detect from luis.ai are "SearchVSTF" to search for an item, and "CreateVSTF" to create an item. I coded in a few other commands like /topfeatures to execute specific queries. 10 | 11 | I also added a method in the controller to handle Active Directory authentication. If a bot user hasn't authenticated, it directs them to login first. 12 | 13 | ### Logic Apps ### 14 | 15 | If a query or command is ever needed, the Bot Host will simply trigger a Logic App and wait for the response. The Logic Apps each accept the request from the Bot Host (or any other host that may be using these Logic Apps), and use conditions and a custom API (VSTS API App) to execute against Visual Studio Team Services. 16 | 17 | ### VSTS Custom API ### 18 | 19 | Custom API App I hosted in Azure to connect to Visual Studio Team Services. It exposes Swagger metadata the Logic App can read to execute the commands as necessary. If talking to an on-premise VSTS, Azure Hybrid Connectivity can be enabled. -------------------------------------------------------------------------------- /VSTS_API/.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /VSTS_API/.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | build/ 21 | bld/ 22 | [Bb]in/ 23 | [Oo]bj/ 24 | [Pp]ublishProfiles/ 25 | 26 | # Visual Studio 2015 cache/options directory 27 | .vs/ 28 | 29 | # MSTest test Results 30 | [Tt]est[Rr]esult*/ 31 | [Bb]uild[Ll]og.* 32 | 33 | # NUNIT 34 | *.VisualState.xml 35 | TestResult.xml 36 | 37 | # Build Results of an ATL Project 38 | [Dd]ebugPS/ 39 | [Rr]eleasePS/ 40 | dlldata.c 41 | 42 | # DNX 43 | project.lock.json 44 | artifacts/ 45 | 46 | *_i.c 47 | *_p.c 48 | *_i.h 49 | *.ilk 50 | *.meta 51 | *.obj 52 | *.pch 53 | *.pdb 54 | *.pgc 55 | *.pgd 56 | *.rsp 57 | *.sbr 58 | *.tlb 59 | *.tli 60 | *.tlh 61 | *.tmp 62 | *.tmp_proj 63 | *.log 64 | *.vspscc 65 | *.vssscc 66 | .builds 67 | *.pidb 68 | *.svclog 69 | *.scc 70 | 71 | # Chutzpah Test files 72 | _Chutzpah* 73 | 74 | # Visual C++ cache files 75 | ipch/ 76 | *.aps 77 | *.ncb 78 | *.opensdf 79 | *.sdf 80 | *.cachefile 81 | 82 | # Visual Studio profiler 83 | *.psess 84 | *.vsp 85 | *.vspx 86 | 87 | # TFS 2012 Local Workspace 88 | $tf/ 89 | 90 | # Guidance Automation Toolkit 91 | *.gpState 92 | 93 | # ReSharper is a .NET coding add-in 94 | _ReSharper*/ 95 | *.[Rr]e[Ss]harper 96 | *.DotSettings.user 97 | 98 | # JustCode is a .NET coding add-in 99 | .JustCode 100 | 101 | # TeamCity is a build add-in 102 | _TeamCity* 103 | 104 | # DotCover is a Code Coverage Tool 105 | *.dotCover 106 | 107 | # NCrunch 108 | _NCrunch_* 109 | .*crunch*.local.xml 110 | 111 | # MightyMoose 112 | *.mm.* 113 | AutoTest.Net/ 114 | 115 | # Web workbench (sass) 116 | .sass-cache/ 117 | 118 | # Installshield output folder 119 | [Ee]xpress/ 120 | 121 | # DocProject is a documentation generator add-in 122 | DocProject/buildhelp/ 123 | DocProject/Help/*.HxT 124 | DocProject/Help/*.HxC 125 | DocProject/Help/*.hhc 126 | DocProject/Help/*.hhk 127 | DocProject/Help/*.hhp 128 | DocProject/Help/Html2 129 | DocProject/Help/html 130 | 131 | # Click-Once directory 132 | publish/ 133 | 134 | # Publish Web Output 135 | *.[Pp]ublish.xml 136 | *.azurePubxml 137 | ## TODO: Comment the next line if you want to checkin your 138 | ## web deploy settings but do note that will include unencrypted 139 | ## passwords 140 | #*.pubxml 141 | 142 | *.publishproj 143 | 144 | # NuGet Packages 145 | *.nupkg 146 | # The packages folder can be ignored because of Package Restore 147 | **/packages/* 148 | # except build/, which is used as an MSBuild target. 149 | !**/packages/build/ 150 | # Uncomment if necessary however generally it will be regenerated when needed 151 | #!**/packages/repositories.config 152 | 153 | # Windows Azure Build Output 154 | csx/ 155 | *.build.csdef 156 | 157 | # Windows Store app package directory 158 | AppPackages/ 159 | 160 | # Visual Studio cache files 161 | # files ending in .cache can be ignored 162 | *.[Cc]ache 163 | # but keep track of directories ending in .cache 164 | !*.[Cc]ache/ 165 | 166 | # Others 167 | ClientBin/ 168 | [Ss]tyle[Cc]op.* 169 | ~$* 170 | *~ 171 | *.dbmdl 172 | *.dbproj.schemaview 173 | *.pfx 174 | *.publishsettings 175 | node_modules/ 176 | orleans.codegen.cs 177 | 178 | # RIA/Silverlight projects 179 | Generated_Code/ 180 | 181 | # Backup & report files from converting an old project file 182 | # to a newer Visual Studio version. Backup files are not needed, 183 | # because we have git ;-) 184 | _UpgradeReport_Files/ 185 | Backup*/ 186 | UpgradeLog*.XML 187 | UpgradeLog*.htm 188 | 189 | # SQL Server files 190 | *.mdf 191 | *.ldf 192 | 193 | # Business Intelligence projects 194 | *.rdl.data 195 | *.bim.layout 196 | *.bim_*.settings 197 | 198 | # Microsoft Fakes 199 | FakesAssemblies/ 200 | 201 | # Node.js Tools for Visual Studio 202 | .ntvs_analysis.dat 203 | 204 | # Visual Studio 6 build log 205 | *.plg 206 | 207 | # Visual Studio 6 workspace options file 208 | *.opt 209 | 210 | # LightSwitch generated files 211 | GeneratedArtifacts/ 212 | _Pvt_Extensions/ 213 | ModelManifest.xml 214 | -------------------------------------------------------------------------------- /VSTS_API/VSTS_API.Tests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("VSTS_API.Tests")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("VSTS_API.Tests")] 13 | [assembly: AssemblyCopyright("Copyright © 2016")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("b97a3eb0-b719-4f01-b5ba-24312490533e")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /VSTS_API/VSTS_API.Tests/UnitTest1.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | 4 | namespace VSTS_API.Tests 5 | { 6 | [TestClass] 7 | public class UnitTest1 8 | { 9 | [TestMethod] 10 | public void TestMethod1() 11 | { 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /VSTS_API/VSTS_API.Tests/VSTS_API.Tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | {B97A3EB0-B719-4F01-B5BA-24312490533E} 7 | Library 8 | Properties 9 | VSTS_API.Tests 10 | VSTS_API.Tests 11 | v4.5.2 12 | 512 13 | {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 14 | False 15 | UnitTest 16 | 17 | 18 | 19 | 20 | true 21 | full 22 | false 23 | bin\Debug\ 24 | DEBUG;TRACE 25 | prompt 26 | 4 27 | 28 | 29 | pdbonly 30 | true 31 | bin\Release\ 32 | TRACE 33 | prompt 34 | 4 35 | 36 | 37 | 38 | 39 | ..\packages\Microsoft.IdentityModel.Clients.ActiveDirectory.2.16.204221202\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.dll 40 | True 41 | 42 | 43 | ..\packages\Microsoft.IdentityModel.Clients.ActiveDirectory.2.16.204221202\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.WindowsForms.dll 44 | True 45 | 46 | 47 | ..\packages\WindowsAzure.ServiceBus.2.5.1.0\lib\net40-full\Microsoft.ServiceBus.dll 48 | True 49 | 50 | 51 | ..\packages\Microsoft.TeamFoundationServer.ExtendedClient.14.89.0\lib\net45\Microsoft.TeamFoundation.Build.Client.dll 52 | True 53 | 54 | 55 | ..\packages\Microsoft.TeamFoundationServer.ExtendedClient.14.89.0\lib\net45\Microsoft.TeamFoundation.Build.Common.dll 56 | True 57 | 58 | 59 | ..\packages\Microsoft.TeamFoundationServer.Client.14.89.0\lib\net45\Microsoft.TeamFoundation.Build2.WebApi.dll 60 | True 61 | 62 | 63 | ..\packages\Microsoft.TeamFoundationServer.Client.14.89.0\lib\net45\Microsoft.TeamFoundation.Chat.WebApi.dll 64 | True 65 | 66 | 67 | ..\packages\Microsoft.TeamFoundationServer.ExtendedClient.14.89.0\lib\net45\Microsoft.TeamFoundation.Client.dll 68 | True 69 | 70 | 71 | ..\packages\Microsoft.VisualStudio.Services.Client.14.89.0\lib\net45\Microsoft.TeamFoundation.Common.dll 72 | True 73 | 74 | 75 | ..\packages\Microsoft.TeamFoundationServer.Client.14.89.0\lib\net45\Microsoft.TeamFoundation.Core.WebApi.dll 76 | True 77 | 78 | 79 | ..\packages\Microsoft.TeamFoundationServer.ExtendedClient.14.89.0\lib\net45\Microsoft.TeamFoundation.DeleteTeamProject.dll 80 | True 81 | 82 | 83 | ..\packages\Microsoft.TeamFoundationServer.ExtendedClient.14.89.0\lib\net45\Microsoft.TeamFoundation.Diff.dll 84 | True 85 | 86 | 87 | ..\packages\Microsoft.TeamFoundationServer.ExtendedClient.14.89.0\lib\net45\Microsoft.TeamFoundation.Discussion.Client.dll 88 | True 89 | 90 | 91 | ..\packages\Microsoft.TeamFoundationServer.ExtendedClient.14.89.0\lib\net45\Microsoft.TeamFoundation.Git.Client.dll 92 | True 93 | 94 | 95 | ..\packages\Microsoft.TeamFoundationServer.ExtendedClient.14.89.0\lib\net45\Microsoft.TeamFoundation.Lab.Client.dll 96 | True 97 | 98 | 99 | ..\packages\Microsoft.TeamFoundationServer.ExtendedClient.14.89.0\lib\net45\Microsoft.TeamFoundation.Lab.Common.dll 100 | True 101 | 102 | 103 | ..\packages\Microsoft.TeamFoundationServer.ExtendedClient.14.89.0\lib\net45\Microsoft.TeamFoundation.Lab.TestIntegration.Client.dll 104 | True 105 | 106 | 107 | ..\packages\Microsoft.TeamFoundationServer.ExtendedClient.14.89.0\lib\net45\Microsoft.TeamFoundation.Lab.WorkflowIntegration.Client.dll 108 | True 109 | 110 | 111 | ..\packages\Microsoft.TeamFoundationServer.Client.14.89.0\lib\net45\Microsoft.TeamFoundation.Policy.WebApi.dll 112 | True 113 | 114 | 115 | ..\packages\Microsoft.TeamFoundationServer.ExtendedClient.14.89.0\lib\net45\Microsoft.TeamFoundation.ProjectManagement.dll 116 | True 117 | 118 | 119 | ..\packages\Microsoft.TeamFoundationServer.ExtendedClient.14.89.0\lib\net45\Microsoft.TeamFoundation.SharePointReporting.Integration.dll 120 | True 121 | 122 | 123 | ..\packages\Microsoft.TeamFoundationServer.Client.14.89.0\lib\net45\Microsoft.TeamFoundation.SourceControl.WebApi.dll 124 | True 125 | 126 | 127 | ..\packages\Microsoft.TeamFoundationServer.Client.14.89.0\lib\net45\Microsoft.TeamFoundation.Test.WebApi.dll 128 | True 129 | 130 | 131 | ..\packages\Microsoft.TeamFoundationServer.ExtendedClient.14.89.0\lib\net45\Microsoft.TeamFoundation.TestImpact.Client.dll 132 | True 133 | 134 | 135 | ..\packages\Microsoft.TeamFoundationServer.ExtendedClient.14.89.0\lib\net45\Microsoft.TeamFoundation.TestManagement.Client.dll 136 | True 137 | 138 | 139 | ..\packages\Microsoft.TeamFoundationServer.ExtendedClient.14.89.0\lib\net45\Microsoft.TeamFoundation.TestManagement.Common.dll 140 | True 141 | 142 | 143 | ..\packages\Microsoft.TeamFoundationServer.Client.14.89.0\lib\net45\Microsoft.TeamFoundation.TestManagement.WebApi.dll 144 | True 145 | 146 | 147 | ..\packages\Microsoft.TeamFoundationServer.ExtendedClient.14.89.0\lib\net45\Microsoft.TeamFoundation.VersionControl.Client.dll 148 | True 149 | 150 | 151 | ..\packages\Microsoft.TeamFoundationServer.ExtendedClient.14.89.0\lib\net45\Microsoft.TeamFoundation.VersionControl.Common.dll 152 | True 153 | 154 | 155 | ..\packages\Microsoft.TeamFoundationServer.ExtendedClient.14.89.0\lib\net45\Microsoft.TeamFoundation.VersionControl.Common.Integration.dll 156 | True 157 | 158 | 159 | ..\packages\Microsoft.TeamFoundationServer.Client.14.89.0\lib\net45\Microsoft.TeamFoundation.Work.WebApi.dll 160 | True 161 | 162 | 163 | ..\packages\Microsoft.TeamFoundationServer.ExtendedClient.14.89.0\lib\net45\Microsoft.TeamFoundation.WorkItemTracking.Client.dll 164 | True 165 | 166 | 167 | ..\packages\Microsoft.TeamFoundationServer.ExtendedClient.14.89.0\lib\net45\Microsoft.TeamFoundation.WorkItemTracking.Client.DataStoreLoader.dll 168 | True 169 | 170 | 171 | ..\packages\Microsoft.TeamFoundationServer.ExtendedClient.14.89.0\lib\net45\Microsoft.TeamFoundation.WorkItemTracking.Client.QueryLanguage.dll 172 | True 173 | 174 | 175 | ..\packages\Microsoft.TeamFoundationServer.ExtendedClient.14.89.0\lib\net45\Microsoft.TeamFoundation.WorkItemTracking.Common.dll 176 | True 177 | 178 | 179 | ..\packages\Microsoft.TeamFoundationServer.ExtendedClient.14.89.0\lib\net45\Microsoft.TeamFoundation.WorkItemTracking.Proxy.dll 180 | True 181 | 182 | 183 | ..\packages\Microsoft.TeamFoundationServer.Client.14.89.0\lib\net45\Microsoft.TeamFoundation.WorkItemTracking.WebApi.dll 184 | True 185 | 186 | 187 | 188 | ..\packages\Microsoft.VisualStudio.Services.InteractiveClient.14.89.0\lib\net45\Microsoft.VisualStudio.Services.Client.dll 189 | True 190 | 191 | 192 | ..\packages\Microsoft.VisualStudio.Services.Client.14.89.0\lib\net45\Microsoft.VisualStudio.Services.Common.dll 193 | True 194 | 195 | 196 | ..\packages\Microsoft.VisualStudio.Services.Client.14.89.0\lib\net45\Microsoft.VisualStudio.Services.WebApi.dll 197 | True 198 | 199 | 200 | ..\packages\Microsoft.WindowsAzure.ConfigurationManager.1.7.0.0\lib\net35-full\Microsoft.WindowsAzure.Configuration.dll 201 | True 202 | 203 | 204 | ..\packages\Newtonsoft.Json.6.0.5\lib\net45\Newtonsoft.Json.dll 205 | True 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | ..\packages\System.IdentityModel.Tokens.Jwt.4.0.0\lib\net45\System.IdentityModel.Tokens.Jwt.dll 214 | True 215 | 216 | 217 | 218 | ..\packages\Microsoft.AspNet.WebApi.Client.5.2.2\lib\net45\System.Net.Http.Formatting.dll 219 | True 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | ..\packages\Microsoft.AspNet.WebApi.Core.5.2.2\lib\net45\System.Web.Http.dll 229 | True 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | {F3A9B11F-BA25-4FB8-95CD-A53D1B1E40F3} 242 | VSTS_API 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. 255 | 256 | 257 | 258 | 265 | -------------------------------------------------------------------------------- /VSTS_API/VSTS_API.Tests/app.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /VSTS_API/VSTS_API.Tests/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /VSTS_API/VSTS_API.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.24720.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VSTS_API", "VSTS_API\VSTS_API.csproj", "{F3A9B11F-BA25-4FB8-95CD-A53D1B1E40F3}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VSTS_API.Tests", "VSTS_API.Tests\VSTS_API.Tests.csproj", "{B97A3EB0-B719-4F01-B5BA-24312490533E}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Release|Any CPU = Release|Any CPU 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {F3A9B11F-BA25-4FB8-95CD-A53D1B1E40F3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 17 | {F3A9B11F-BA25-4FB8-95CD-A53D1B1E40F3}.Debug|Any CPU.Build.0 = Debug|Any CPU 18 | {F3A9B11F-BA25-4FB8-95CD-A53D1B1E40F3}.Release|Any CPU.ActiveCfg = Release|Any CPU 19 | {F3A9B11F-BA25-4FB8-95CD-A53D1B1E40F3}.Release|Any CPU.Build.0 = Release|Any CPU 20 | {B97A3EB0-B719-4F01-B5BA-24312490533E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {B97A3EB0-B719-4F01-B5BA-24312490533E}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {B97A3EB0-B719-4F01-B5BA-24312490533E}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {B97A3EB0-B719-4F01-B5BA-24312490533E}.Release|Any CPU.Build.0 = Release|Any CPU 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | EndGlobal 29 | -------------------------------------------------------------------------------- /VSTS_API/VSTS_API/App_Start/SwaggerConfig.cs: -------------------------------------------------------------------------------- 1 | using System.Web.Http; 2 | using WebActivatorEx; 3 | using VSTS_API; 4 | using Swashbuckle.Application; 5 | using TRex.Metadata; 6 | 7 | [assembly: PreApplicationStartMethod(typeof(SwaggerConfig), "Register")] 8 | 9 | namespace VSTS_API 10 | { 11 | public class SwaggerConfig 12 | { 13 | public static void Register() 14 | { 15 | var thisAssembly = typeof(SwaggerConfig).Assembly; 16 | 17 | GlobalConfiguration.Configuration 18 | .EnableSwagger(c => 19 | { 20 | // By default, the service root url is inferred from the request used to access the docs. 21 | // However, there may be situations (e.g. proxy and load-balanced environments) where this does not 22 | // resolve correctly. You can workaround this by providing your own code to determine the root URL. 23 | // 24 | //c.RootUrl(req => GetRootUrlFromAppConfig()); 25 | 26 | // If schemes are not explicitly provided in a Swagger 2.0 document, then the scheme used to access 27 | // the docs is taken as the default. If your API supports multiple schemes and you want to be explicit 28 | // about them, you can use the "Schemes" option as shown below. 29 | // 30 | //c.Schemes(new[] { "http", "https" }); 31 | 32 | // Use "SingleApiVersion" to describe a single version API. Swagger 2.0 includes an "Info" object to 33 | // hold additional metadata for an API. Version and title are required but you can also provide 34 | // additional fields by chaining methods off SingleApiVersion. 35 | // 36 | c.SingleApiVersion("v1", "VSTS_API"); 37 | c.ReleaseTheTRex(); 38 | 39 | // If your API has multiple versions, use "MultipleApiVersions" instead of "SingleApiVersion". 40 | // In this case, you must provide a lambda that tells Swashbuckle which actions should be 41 | // included in the docs for a given API version. Like "SingleApiVersion", each call to "Version" 42 | // returns an "Info" builder so you can provide additional metadata per API version. 43 | // 44 | //c.MultipleApiVersions( 45 | // (apiDesc, targetApiVersion) => ResolveVersionSupportByRouteConstraint(apiDesc, targetApiVersion), 46 | // (vc) => 47 | // { 48 | // vc.Version("v2", "Swashbuckle Dummy API V2"); 49 | // vc.Version("v1", "Swashbuckle Dummy API V1"); 50 | // }); 51 | 52 | // You can use "BasicAuth", "ApiKey" or "OAuth2" options to describe security schemes for the API. 53 | // See https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md for more details. 54 | // NOTE: These only define the schemes and need to be coupled with a corresponding "security" property 55 | // at the document or operation level to indicate which schemes are required for an operation. To do this, 56 | // you'll need to implement a custom IDocumentFilter and/or IOperationFilter to set these properties 57 | // according to your specific authorization implementation 58 | // 59 | //c.BasicAuth("basic") 60 | // .Description("Basic HTTP Authentication"); 61 | // 62 | //c.ApiKey("apiKey") 63 | // .Description("API Key Authentication") 64 | // .Name("apiKey") 65 | // .In("header"); 66 | // 67 | //c.OAuth2("oauth2") 68 | // .Description("OAuth2 Implicit Grant") 69 | // .Flow("implicit") 70 | // .AuthorizationUrl("http://petstore.swagger.wordnik.com/api/oauth/dialog") 71 | // //.TokenUrl("https://tempuri.org/token") 72 | // .Scopes(scopes => 73 | // { 74 | // scopes.Add("read", "Read access to protected resources"); 75 | // scopes.Add("write", "Write access to protected resources"); 76 | // }); 77 | 78 | // Set this flag to omit descriptions for any actions decorated with the Obsolete attribute 79 | //c.IgnoreObsoleteActions(); 80 | 81 | // Each operation be assigned one or more tags which are then used by consumers for various reasons. 82 | // For example, the swagger-ui groups operations according to the first tag of each operation. 83 | // By default, this will be controller name but you can use the "GroupActionsBy" option to 84 | // override with any value. 85 | // 86 | //c.GroupActionsBy(apiDesc => apiDesc.HttpMethod.ToString()); 87 | 88 | // You can also specify a custom sort order for groups (as defined by "GroupActionsBy") to dictate 89 | // the order in which operations are listed. For example, if the default grouping is in place 90 | // (controller name) and you specify a descending alphabetic sort order, then actions from a 91 | // ProductsController will be listed before those from a CustomersController. This is typically 92 | // used to customize the order of groupings in the swagger-ui. 93 | // 94 | //c.OrderActionGroupsBy(new DescendingAlphabeticComparer()); 95 | 96 | // If you annotate Controllers and API Types with 97 | // Xml comments (http://msdn.microsoft.com/en-us/library/b2s063f7(v=vs.110).aspx), you can incorporate 98 | // those comments into the generated docs and UI. You can enable this by providing the path to one or 99 | // more Xml comment files. 100 | // 101 | //c.IncludeXmlComments(GetXmlCommentsPath()); 102 | 103 | // Swashbuckle makes a best attempt at generating Swagger compliant JSON schemas for the various types 104 | // exposed in your API. However, there may be occasions when more control of the output is needed. 105 | // This is supported through the "MapType" and "SchemaFilter" options: 106 | // 107 | // Use the "MapType" option to override the Schema generation for a specific type. 108 | // It should be noted that the resulting Schema will be placed "inline" for any applicable Operations. 109 | // While Swagger 2.0 supports inline definitions for "all" Schema types, the swagger-ui tool does not. 110 | // It expects "complex" Schemas to be defined separately and referenced. For this reason, you should only 111 | // use the "MapType" option when the resulting Schema is a primitive or array type. If you need to alter a 112 | // complex Schema, use a Schema filter. 113 | // 114 | //c.MapType(() => new Schema { type = "integer", format = "int32" }); 115 | 116 | // If you want to post-modify "complex" Schemas once they've been generated, across the board or for a 117 | // specific type, you can wire up one or more Schema filters. 118 | // 119 | //c.SchemaFilter(); 120 | 121 | // In a Swagger 2.0 document, complex types are typically declared globally and referenced by unique 122 | // Schema Id. By default, Swashbuckle does NOT use the full type name in Schema Ids. In most cases, this 123 | // works well because it prevents the "implementation detail" of type namespaces from leaking into your 124 | // Swagger docs and UI. However, if you have multiple types in your API with the same class name, you'll 125 | // need to opt out of this behavior to avoid Schema Id conflicts. 126 | // 127 | //c.UseFullTypeNameInSchemaIds(); 128 | 129 | // Alternatively, you can provide your own custom strategy for inferring SchemaId's for 130 | // describing "complex" types in your API. 131 | // 132 | //c.SchemaId(t => t.FullName.Contains('`') ? t.FullName.Substring(0, t.FullName.IndexOf('`')) : t.FullName); 133 | 134 | // Set this flag to omit schema property descriptions for any type properties decorated with the 135 | // Obsolete attribute 136 | //c.IgnoreObsoleteProperties(); 137 | 138 | // In accordance with the built in JsonSerializer, Swashbuckle will, by default, describe enums as integers. 139 | // You can change the serializer behavior by configuring the StringToEnumConverter globally or for a given 140 | // enum type. Swashbuckle will honor this change out-of-the-box. However, if you use a different 141 | // approach to serialize enums as strings, you can also force Swashbuckle to describe them as strings. 142 | // 143 | //c.DescribeAllEnumsAsStrings(); 144 | 145 | // Similar to Schema filters, Swashbuckle also supports Operation and Document filters: 146 | // 147 | // Post-modify Operation descriptions once they've been generated by wiring up one or more 148 | // Operation filters. 149 | // 150 | //c.OperationFilter(); 151 | // 152 | // If you've defined an OAuth2 flow as described above, you could use a custom filter 153 | // to inspect some attribute on each action and infer which (if any) OAuth2 scopes are required 154 | // to execute the operation 155 | // 156 | //c.OperationFilter(); 157 | 158 | // Post-modify the entire Swagger document by wiring up one or more Document filters. 159 | // This gives full control to modify the final SwaggerDocument. You should have a good understanding of 160 | // the Swagger 2.0 spec. - https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md 161 | // before using this option. 162 | // 163 | //c.DocumentFilter(); 164 | 165 | // In contrast to WebApi, Swagger 2.0 does not include the query string component when mapping a URL 166 | // to an action. As a result, Swashbuckle will raise an exception if it encounters multiple actions 167 | // with the same path (sans query string) and HTTP method. You can workaround this by providing a 168 | // custom strategy to pick a winner or merge the descriptions for the purposes of the Swagger docs 169 | // 170 | //c.ResolveConflictingActions(apiDescriptions => apiDescriptions.First()); 171 | 172 | // Wrap the default SwaggerGenerator with additional behavior (e.g. caching) or provide an 173 | // alternative implementation for ISwaggerProvider with the CustomProvider option. 174 | // 175 | //c.CustomProvider((defaultProvider) => new CachingSwaggerProvider(defaultProvider)); 176 | }) 177 | .EnableSwaggerUi(c => 178 | { 179 | // Use the "InjectStylesheet" option to enrich the UI with one or more additional CSS stylesheets. 180 | // The file must be included in your project as an "Embedded Resource", and then the resource's 181 | // "Logical Name" is passed to the method as shown below. 182 | // 183 | //c.InjectStylesheet(containingAssembly, "Swashbuckle.Dummy.SwaggerExtensions.testStyles1.css"); 184 | 185 | // Use the "InjectJavaScript" option to invoke one or more custom JavaScripts after the swagger-ui 186 | // has loaded. The file must be included in your project as an "Embedded Resource", and then the resource's 187 | // "Logical Name" is passed to the method as shown above. 188 | // 189 | //c.InjectJavaScript(thisAssembly, "Swashbuckle.Dummy.SwaggerExtensions.testScript1.js"); 190 | 191 | // The swagger-ui renders boolean data types as a dropdown. By default, it provides "true" and "false" 192 | // strings as the possible choices. You can use this option to change these to something else, 193 | // for example 0 and 1. 194 | // 195 | //c.BooleanValues(new[] { "0", "1" }); 196 | 197 | // By default, swagger-ui will validate specs against swagger.io's online validator and display the result 198 | // in a badge at the bottom of the page. Use these options to set a different validator URL or to disable the 199 | // feature entirely. 200 | //c.SetValidatorUrl("http://localhost/validator"); 201 | //c.DisableValidator(); 202 | 203 | // Use this option to control how the Operation listing is displayed. 204 | // It can be set to "None" (default), "List" (shows operations for each resource), 205 | // or "Full" (fully expanded: shows operations and their details). 206 | // 207 | //c.DocExpansion(DocExpansion.List); 208 | 209 | // Use the CustomAsset option to provide your own version of assets used in the swagger-ui. 210 | // It's typically used to instruct Swashbuckle to return your version instead of the default 211 | // when a request is made for "index.html". As with all custom content, the file must be included 212 | // in your project as an "Embedded Resource", and then the resource's "Logical Name" is passed to 213 | // the method as shown below. 214 | // 215 | //c.CustomAsset("index", containingAssembly, "YourWebApiProject.SwaggerExtensions.index.html"); 216 | 217 | // If your API has multiple versions and you've applied the MultipleApiVersions setting 218 | // as described above, you can also enable a select box in the swagger-ui, that displays 219 | // a discovery URL for each version. This provides a convenient way for users to browse documentation 220 | // for different API versions. 221 | // 222 | //c.EnableDiscoveryUrlSelector(); 223 | 224 | // If your API supports the OAuth2 Implicit flow, and you've described it correctly, according to 225 | // the Swagger 2.0 specification, you can enable UI support as shown below. 226 | // 227 | //c.EnableOAuth2Support("test-client-id", "test-realm", "Swagger UI"); 228 | }); 229 | } 230 | } 231 | } 232 | -------------------------------------------------------------------------------- /VSTS_API/VSTS_API/App_Start/Utils.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | 6 | namespace VSTS_API.App_Start 7 | { 8 | public static class Utils 9 | { 10 | internal static string GetTFSType(string type) 11 | { 12 | if (type.ToLower().Contains("backlog") || type.ToLower().Contains("feature")) 13 | { 14 | return "Product Backlog Item"; 15 | } 16 | else 17 | { 18 | return "Bug"; 19 | } 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /VSTS_API/VSTS_API/App_Start/WebApiConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web.Http; 5 | 6 | namespace VSTS_API 7 | { 8 | public static class WebApiConfig 9 | { 10 | public static void Register(HttpConfiguration config) 11 | { 12 | // Web API configuration and services 13 | 14 | // Web API routes 15 | config.MapHttpAttributeRoutes(); 16 | 17 | config.Routes.MapHttpRoute( 18 | name: "DefaultApi", 19 | routeTemplate: "api/{controller}/{id}", 20 | defaults: new { id = RouteParameter.Optional } 21 | ); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /VSTS_API/VSTS_API/Controllers/CreateItemController.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.TeamFoundation.Client; 2 | using Microsoft.TeamFoundation.WorkItemTracking.Client; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Configuration; 6 | using System.Linq; 7 | using System.Net; 8 | using System.Net.Http; 9 | using System.Web.Http; 10 | using TRex.Metadata; 11 | using VSTS_API.App_Start; 12 | using VSTS_API.Models; 13 | 14 | namespace VSTF_API.Controllers 15 | { 16 | public class CreateItemController : ApiController 17 | { 18 | private string username = ConfigurationManager.AppSettings["uname"]; 19 | private string password = ConfigurationManager.AppSettings["pword"]; 20 | private string domain = ConfigurationManager.AppSettings["domain"]; 21 | [Metadata(friendlyName: "Create New Item", description: "Create New Item in VSTS")] 22 | [Swashbuckle.Swagger.Annotations.SwaggerResponse(HttpStatusCode.OK, "New Work Item", typeof(SimpleWorkItem))] 23 | [HttpPost, Route("api/tfs/create")] 24 | public HttpResponseMessage CreateItem([FromUri] string requestedCollectionUri, [FromUri] string requestedProject, [FromBody] SimpleWorkItem requestedWorkItem) 25 | { 26 | 27 | Uri collectionUri = new Uri(requestedCollectionUri); 28 | TfsTeamProjectCollection tpc = new TfsTeamProjectCollection(collectionUri, new NetworkCredential(username, password, domain)); 29 | WorkItemStore workItemStore = tpc.GetService(); 30 | Project teamProject = workItemStore.Projects[requestedProject]; 31 | WorkItemType workItemType = teamProject.WorkItemTypes[Utils.GetTFSType(requestedWorkItem.Type)]; 32 | 33 | // Create the work item. 34 | WorkItem newWorkItem = new WorkItem(workItemType) 35 | { 36 | // The title is generally the only required field that doesn’t have a default value. 37 | // You must set it, or you can’t save the work item. If you’re working with another 38 | // type of work item, there may be other fields that you’ll have to set. 39 | Title = requestedWorkItem.Title, 40 | AreaPath = requestedWorkItem.AreaPath, 41 | State = requestedWorkItem.State, 42 | IterationPath = requestedWorkItem.IterationPath, 43 | 44 | }; 45 | RelatedLink parent = new RelatedLink(workItemStore.WorkItemLinkTypes.LinkTypeEnds[requestedWorkItem.LinkType], requestedWorkItem.LinkId); 46 | newWorkItem.Links.Add(parent); 47 | newWorkItem.Save(); 48 | requestedWorkItem.id = newWorkItem.Id; 49 | return Request.CreateResponse(HttpStatusCode.OK, requestedWorkItem); 50 | 51 | } 52 | 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /VSTS_API/VSTS_API/Controllers/ExecuteQueryController.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.TeamFoundation.Client; 2 | using Microsoft.TeamFoundation.WorkItemTracking.Client; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Configuration; 6 | using System.Linq; 7 | using System.Net; 8 | using System.Net.Http; 9 | using System.Web.Http; 10 | using VSTS_API.App_Start; 11 | using VSTS_API.Models; 12 | 13 | namespace VSTS_API.Controllers 14 | { 15 | public class ExecuteQueryController : ApiController 16 | { 17 | private string username = ConfigurationManager.AppSettings["uname"]; 18 | private string password = ConfigurationManager.AppSettings["pword"]; 19 | private string domain = ConfigurationManager.AppSettings["domain"]; 20 | 21 | 22 | public HttpResponseMessage getTopItems([FromUri] string requestedCollectionUri, [FromUri] string requestedProject, [FromUri] int count, [FromUri] string query) 23 | { 24 | Uri collectionUri = new Uri(requestedCollectionUri); 25 | TfsTeamProjectCollection tpc = new TfsTeamProjectCollection(collectionUri, new NetworkCredential(username, password, domain)); 26 | WorkItemStore workItemStore = tpc.GetService(); 27 | WorkItemCollection queryResults = workItemStore.Query(query); 28 | var response = (from WorkItem r in queryResults 29 | select new SimpleWorkItem 30 | { 31 | Title = r.Title, 32 | State = r.State, 33 | id = r.Id, 34 | AreaPath = r.AreaPath, 35 | IterationPath = r.IterationPath, 36 | Type = r.Type.Name 37 | }).Take(count); 38 | 39 | return Request.CreateResponse(HttpStatusCode.OK, response); 40 | } 41 | } 42 | 43 | public class ExecuteRequest 44 | { 45 | public string query { get; set; } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /VSTS_API/VSTS_API/Controllers/SearchItemController.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.TeamFoundation.Client; 2 | using Microsoft.TeamFoundation.WorkItemTracking.Client; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Configuration; 6 | using System.Linq; 7 | using System.Net; 8 | using System.Net.Http; 9 | using System.Web.Http; 10 | using TRex.Metadata; 11 | using VSTS_API.App_Start; 12 | using VSTS_API.Models; 13 | 14 | namespace VSTS_API.Controllers 15 | { 16 | public class SearchItemController : ApiController 17 | { 18 | private string username = ConfigurationManager.AppSettings["uname"]; 19 | private string password = ConfigurationManager.AppSettings["pword"]; 20 | private string domain = ConfigurationManager.AppSettings["domain"]; 21 | 22 | [HttpPost, Route("api/tfs/search")] 23 | [Metadata("Search TFS")] 24 | public HttpResponseMessage SearchItem([FromUri] string requestedCollectionUri, [FromUri] string requestedProject, [FromUri] int count, [FromBody] BasicQuery query) 25 | { 26 | string type = Utils.GetTFSType(query.type); 27 | string filter = query.query; 28 | 29 | Uri collectionUri = new Uri(requestedCollectionUri); 30 | TfsTeamProjectCollection tpc = new TfsTeamProjectCollection(collectionUri, new NetworkCredential(username, password, domain)); 31 | WorkItemStore workItemStore = tpc.GetService(); 32 | WorkItemCollection queryResults = workItemStore.Query( 33 | "Select [Title], [State], [Id], [Stack Rank] " + 34 | "From Workitems " + 35 | "Where [Work Item Type] = '" + type + "' and [State] != 'Removed' and [State] != 'Closed' and " + 36 | "[State] != 'Resolved' and [Title] contains '" + filter + "' " + 37 | "Order By [Stack Rank] Asc" 38 | ); 39 | var response = (from WorkItem r in queryResults select new SimpleWorkItem { 40 | Title = r.Title, 41 | State = r.State, 42 | id = r.Id, 43 | AreaPath = r.AreaPath, 44 | IterationPath = r.IterationPath, 45 | Type = r.Type.Name 46 | }).Take(count); 47 | 48 | return Request.CreateResponse(HttpStatusCode.OK, response); 49 | 50 | } 51 | 52 | 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /VSTS_API/VSTS_API/Global.asax: -------------------------------------------------------------------------------- 1 | <%@ Application Codebehind="Global.asax.cs" Inherits="VSTS_API.WebApiApplication" Language="C#" %> 2 | -------------------------------------------------------------------------------- /VSTS_API/VSTS_API/Global.asax.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.Http; 6 | using System.Web.Routing; 7 | 8 | namespace VSTS_API 9 | { 10 | public class WebApiApplication : System.Web.HttpApplication 11 | { 12 | protected void Application_Start() 13 | { 14 | GlobalConfiguration.Configure(WebApiConfig.Register); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /VSTS_API/VSTS_API/Models/SimpleWorkItem.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | 6 | namespace VSTS_API.Models 7 | { 8 | public class SimpleWorkItem 9 | { 10 | 11 | public string Type { get; set; } 12 | public string Title { get; set; } 13 | public string AreaPath { get; set; } 14 | public string State { get; set; } 15 | public string IterationPath { get; set; } 16 | public string LinkType { get; set; } 17 | public int LinkId { get; set; } 18 | 19 | public int id { get; set; } 20 | } 21 | 22 | public class BasicQuery 23 | { 24 | public string query { get; set; } 25 | public string type { get; set; } 26 | 27 | } 28 | } -------------------------------------------------------------------------------- /VSTS_API/VSTS_API/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("VSTS_API")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("VSTS_API")] 13 | [assembly: AssemblyCopyright("Copyright © 2016")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("f3a9b11f-ba25-4fb8-95cd-a53d1b1e40f3")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Revision and Build Numbers 33 | // by using the '*' as shown below: 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /VSTS_API/VSTS_API/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace VSTS_API.Properties { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("VSTS_API.Properties.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /VSTS_API/VSTS_API/Properties/Resources.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | text/microsoft-resx 91 | 92 | 93 | 1.3 94 | 95 | 96 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 97 | 98 | 99 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 100 | 101 | -------------------------------------------------------------------------------- /VSTS_API/VSTS_API/VSTS_API.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | Debug 8 | AnyCPU 9 | 10 | 11 | 2.0 12 | {F3A9B11F-BA25-4FB8-95CD-A53D1B1E40F3} 13 | {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} 14 | Library 15 | Properties 16 | VSTS_API 17 | VSTS_API 18 | v4.5.2 19 | true 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | true 30 | full 31 | false 32 | bin\ 33 | DEBUG;TRACE 34 | prompt 35 | 4 36 | 37 | 38 | pdbonly 39 | true 40 | bin\ 41 | TRACE 42 | prompt 43 | 4 44 | 45 | 46 | 47 | ..\packages\Microsoft.Azure.AppService.ApiApps.Service.0.9.64\lib\net45\Microsoft.Azure.AppService.ApiApps.Service.dll 48 | True 49 | 50 | 51 | ..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.0\lib\net45\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.dll 52 | True 53 | 54 | 55 | 56 | ..\packages\Microsoft.IdentityModel.Clients.ActiveDirectory.2.16.204221202\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.dll 57 | True 58 | 59 | 60 | ..\packages\Microsoft.IdentityModel.Clients.ActiveDirectory.2.16.204221202\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.WindowsForms.dll 61 | True 62 | 63 | 64 | ..\packages\WindowsAzure.ServiceBus.2.5.1.0\lib\net40-full\Microsoft.ServiceBus.dll 65 | True 66 | 67 | 68 | ..\packages\Microsoft.TeamFoundationServer.ExtendedClient.14.89.0\lib\net45\Microsoft.TeamFoundation.Build.Client.dll 69 | True 70 | 71 | 72 | ..\packages\Microsoft.TeamFoundationServer.ExtendedClient.14.89.0\lib\net45\Microsoft.TeamFoundation.Build.Common.dll 73 | True 74 | 75 | 76 | ..\packages\Microsoft.TeamFoundationServer.Client.14.89.0\lib\net45\Microsoft.TeamFoundation.Build2.WebApi.dll 77 | True 78 | 79 | 80 | ..\packages\Microsoft.TeamFoundationServer.Client.14.89.0\lib\net45\Microsoft.TeamFoundation.Chat.WebApi.dll 81 | True 82 | 83 | 84 | ..\packages\Microsoft.TeamFoundationServer.ExtendedClient.14.89.0\lib\net45\Microsoft.TeamFoundation.Client.dll 85 | True 86 | 87 | 88 | ..\packages\Microsoft.VisualStudio.Services.Client.14.89.0\lib\net45\Microsoft.TeamFoundation.Common.dll 89 | True 90 | 91 | 92 | ..\packages\Microsoft.TeamFoundationServer.Client.14.89.0\lib\net45\Microsoft.TeamFoundation.Core.WebApi.dll 93 | True 94 | 95 | 96 | ..\packages\Microsoft.TeamFoundationServer.ExtendedClient.14.89.0\lib\net45\Microsoft.TeamFoundation.DeleteTeamProject.dll 97 | True 98 | 99 | 100 | ..\packages\Microsoft.TeamFoundationServer.ExtendedClient.14.89.0\lib\net45\Microsoft.TeamFoundation.Diff.dll 101 | True 102 | 103 | 104 | ..\packages\Microsoft.TeamFoundationServer.ExtendedClient.14.89.0\lib\net45\Microsoft.TeamFoundation.Discussion.Client.dll 105 | True 106 | 107 | 108 | ..\packages\Microsoft.TeamFoundationServer.ExtendedClient.14.89.0\lib\net45\Microsoft.TeamFoundation.Git.Client.dll 109 | True 110 | 111 | 112 | ..\packages\Microsoft.TeamFoundationServer.ExtendedClient.14.89.0\lib\net45\Microsoft.TeamFoundation.Lab.Client.dll 113 | True 114 | 115 | 116 | ..\packages\Microsoft.TeamFoundationServer.ExtendedClient.14.89.0\lib\net45\Microsoft.TeamFoundation.Lab.Common.dll 117 | True 118 | 119 | 120 | ..\packages\Microsoft.TeamFoundationServer.ExtendedClient.14.89.0\lib\net45\Microsoft.TeamFoundation.Lab.TestIntegration.Client.dll 121 | True 122 | 123 | 124 | ..\packages\Microsoft.TeamFoundationServer.ExtendedClient.14.89.0\lib\net45\Microsoft.TeamFoundation.Lab.WorkflowIntegration.Client.dll 125 | True 126 | 127 | 128 | ..\packages\Microsoft.TeamFoundationServer.Client.14.89.0\lib\net45\Microsoft.TeamFoundation.Policy.WebApi.dll 129 | True 130 | 131 | 132 | ..\packages\Microsoft.TeamFoundationServer.ExtendedClient.14.89.0\lib\net45\Microsoft.TeamFoundation.ProjectManagement.dll 133 | True 134 | 135 | 136 | ..\packages\Microsoft.TeamFoundationServer.ExtendedClient.14.89.0\lib\net45\Microsoft.TeamFoundation.SharePointReporting.Integration.dll 137 | True 138 | 139 | 140 | ..\packages\Microsoft.TeamFoundationServer.Client.14.89.0\lib\net45\Microsoft.TeamFoundation.SourceControl.WebApi.dll 141 | True 142 | 143 | 144 | ..\packages\Microsoft.TeamFoundationServer.Client.14.89.0\lib\net45\Microsoft.TeamFoundation.Test.WebApi.dll 145 | True 146 | 147 | 148 | ..\packages\Microsoft.TeamFoundationServer.ExtendedClient.14.89.0\lib\net45\Microsoft.TeamFoundation.TestImpact.Client.dll 149 | True 150 | 151 | 152 | ..\packages\Microsoft.TeamFoundationServer.ExtendedClient.14.89.0\lib\net45\Microsoft.TeamFoundation.TestManagement.Client.dll 153 | True 154 | 155 | 156 | ..\packages\Microsoft.TeamFoundationServer.ExtendedClient.14.89.0\lib\net45\Microsoft.TeamFoundation.TestManagement.Common.dll 157 | True 158 | 159 | 160 | ..\packages\Microsoft.TeamFoundationServer.Client.14.89.0\lib\net45\Microsoft.TeamFoundation.TestManagement.WebApi.dll 161 | True 162 | 163 | 164 | ..\packages\Microsoft.TeamFoundationServer.ExtendedClient.14.89.0\lib\net45\Microsoft.TeamFoundation.VersionControl.Client.dll 165 | True 166 | 167 | 168 | ..\packages\Microsoft.TeamFoundationServer.ExtendedClient.14.89.0\lib\net45\Microsoft.TeamFoundation.VersionControl.Common.dll 169 | True 170 | 171 | 172 | ..\packages\Microsoft.TeamFoundationServer.ExtendedClient.14.89.0\lib\net45\Microsoft.TeamFoundation.VersionControl.Common.Integration.dll 173 | True 174 | 175 | 176 | ..\packages\Microsoft.TeamFoundationServer.Client.14.89.0\lib\net45\Microsoft.TeamFoundation.Work.WebApi.dll 177 | True 178 | 179 | 180 | ..\packages\Microsoft.TeamFoundationServer.ExtendedClient.14.89.0\lib\net45\Microsoft.TeamFoundation.WorkItemTracking.Client.dll 181 | True 182 | 183 | 184 | ..\packages\Microsoft.TeamFoundationServer.ExtendedClient.14.89.0\lib\net45\Microsoft.TeamFoundation.WorkItemTracking.Client.DataStoreLoader.dll 185 | True 186 | 187 | 188 | ..\packages\Microsoft.TeamFoundationServer.ExtendedClient.14.89.0\lib\net45\Microsoft.TeamFoundation.WorkItemTracking.Client.QueryLanguage.dll 189 | True 190 | 191 | 192 | ..\packages\Microsoft.TeamFoundationServer.ExtendedClient.14.89.0\lib\net45\Microsoft.TeamFoundation.WorkItemTracking.Common.dll 193 | True 194 | 195 | 196 | ..\packages\Microsoft.TeamFoundationServer.ExtendedClient.14.89.0\lib\net45\Microsoft.TeamFoundation.WorkItemTracking.Proxy.dll 197 | True 198 | 199 | 200 | ..\packages\Microsoft.TeamFoundationServer.Client.14.89.0\lib\net45\Microsoft.TeamFoundation.WorkItemTracking.WebApi.dll 201 | True 202 | 203 | 204 | ..\packages\Microsoft.VisualStudio.Services.InteractiveClient.14.89.0\lib\net45\Microsoft.VisualStudio.Services.Client.dll 205 | True 206 | 207 | 208 | ..\packages\Microsoft.VisualStudio.Services.Client.14.89.0\lib\net45\Microsoft.VisualStudio.Services.Common.dll 209 | True 210 | 211 | 212 | ..\packages\Microsoft.VisualStudio.Services.Client.14.89.0\lib\net45\Microsoft.VisualStudio.Services.WebApi.dll 213 | True 214 | 215 | 216 | ..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll 217 | True 218 | 219 | 220 | ..\packages\Microsoft.WindowsAzure.ConfigurationManager.1.7.0.0\lib\net35-full\Microsoft.WindowsAzure.Configuration.dll 221 | True 222 | 223 | 224 | ..\packages\Newtonsoft.Json.6.0.5\lib\net45\Newtonsoft.Json.dll 225 | True 226 | 227 | 228 | ..\packages\Swashbuckle.Core.5.3.2\lib\net40\Swashbuckle.Core.dll 229 | True 230 | 231 | 232 | ..\packages\System.IdentityModel.Tokens.Jwt.4.0.0\lib\net45\System.IdentityModel.Tokens.Jwt.dll 233 | True 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | ..\packages\TRex.0.1.7.0\lib\net45\TRex.Metadata.dll 256 | True 257 | 258 | 259 | ..\packages\TRex.Metadata.Attributes.0.1.7.0\lib\portable-net45+win+wpa81+wp80+MonoAndroid10+xamarinios10+MonoTouch10\TRex.Metadata.Attributes.dll 260 | True 261 | 262 | 263 | ..\packages\WebActivatorEx.2.0\lib\net40\WebActivatorEx.dll 264 | True 265 | 266 | 267 | 268 | 269 | ..\packages\Microsoft.AspNet.WebApi.Client.5.2.3\lib\net45\System.Net.Http.Formatting.dll 270 | 271 | 272 | ..\packages\Microsoft.AspNet.WebApi.Core.5.2.3\lib\net45\System.Web.Http.dll 273 | 274 | 275 | ..\packages\Microsoft.AspNet.WebApi.WebHost.5.2.3\lib\net45\System.Web.Http.WebHost.dll 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | Global.asax 291 | 292 | 293 | 294 | 295 | True 296 | True 297 | Resources.resx 298 | 299 | 300 | 301 | 302 | 303 | 304 | Web.config 305 | 306 | 307 | Web.config 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | ResXFileCodeGenerator 316 | Resources.Designer.cs 317 | 318 | 319 | 320 | 10.0 321 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | True 331 | True 332 | 12793 333 | / 334 | http://localhost:12793/ 335 | False 336 | False 337 | 338 | 339 | False 340 | 341 | 342 | 343 | 344 | 345 | 346 | This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. 347 | 348 | 349 | 350 | 351 | 352 | 353 | 360 | -------------------------------------------------------------------------------- /VSTS_API/VSTS_API/Web.Debug.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 18 | 29 | 30 | -------------------------------------------------------------------------------- /VSTS_API/VSTS_API/Web.Release.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 18 | 19 | 30 | 31 | -------------------------------------------------------------------------------- /VSTS_API/VSTS_API/Web.config: -------------------------------------------------------------------------------- 1 |  2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /VSTS_API/VSTS_API/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | --------------------------------------------------------------------------------