Create Work Item in Team Services Through API - c#

I'm trying to create a web app (hosted on Azure) for clients to be able to submit work items to our team services page. Basically a support ticket page so they don't have to call to explain their backlog all the time.
Below is the class and method i've made to create work items, following Microsoft's sample code, with some obvious changes for privacy reasons. This method is triggered by a button click, and so far I cannot get it to create any work items.
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using Newtonsoft.Json;
namespace customapp
{
public class CreateWorkItem
{
public void CreateWorkItemMethod()
{
string personalAccessToken = "xxxxxxxxx";
string credentials = Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(string.Format("{0}:{1}", "xxx", personalAccessToken)));
Object[] patchDocument = new Object[1];
patchDocument[0] = new { op = "add", path = "/fields/System.Title", value = "Test" };
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", credentials);
var patchValue = new StringContent(JsonConvert.SerializeObject(patchDocument), Encoding.UTF8, "application/json-patch+json");
var method = new HttpMethod("PATCH");
var request = new HttpRequestMessage(method, "https://example.visualstudio.com/exampleproject/_apis/wit/workitems/$Support&20Ticket?api-version=1.0") { Content = patchValue };
var response = client.SendAsync(request).Result;
if (response.IsSuccessStatusCode)
{
var result = response.Content.ReadAsStringAsync().Result;
}
}}}}
In the url for the PATCH I am using the team project's ID (in place of /exampleproject you see below). Our site is set up to have an overall project, let's call it ""Master", and inside is a team project for each client, for example "ClientProject". So basically I want to create a "Support Ticket" work item in Master->ClientProject->Backlog/Board.

Using Master\\areapath instead (not Master\areapath).
Sample body:
[
{
"op": "add",
"path": "/fields/System.Title",
"value": "PBIAPI2"
},
{
"op": "add",
"path": "/fields/System.AreaPath",
"value": "Scrum2015\\SharedArea"
}
]
On the other hand, it’s better to create work item by using VSTS/TFS API with Microsoft Team Foundation Server Extended Client package.
Simple sample code:
var u = new Uri("https://[account].visualstudio.com");
VssCredentials c = new VssCredentials(new Microsoft.VisualStudio.Services.Common.VssBasicCredential(string.Empty, "[personal access token]"));
var connection = new VssConnection(u, c);
var workitemClient = connection.GetClient<WorkItemTrackingHttpClient>();
var workitemtype = "Product Backlog Item";
string teamProjectName = "Scrum2015";
var document = new Microsoft.VisualStudio.Services.WebApi.Patch.Json.JsonPatchDocument();
document.Add(
new Microsoft.VisualStudio.Services.WebApi.Patch.Json.JsonPatchOperation()
{
Path = "/fields/Microsoft.VSTS.Common.Discipline",
Operation = Microsoft.VisualStudio.Services.WebApi.Patch.Operation.Add,
Value = "development"
});
document.Add(
new Microsoft.VisualStudio.Services.WebApi.Patch.Json.JsonPatchOperation()
{
Path = "/fields/System.Title",
Operation = Microsoft.VisualStudio.Services.WebApi.Patch.Operation.Add,
Value = string.Format("{0} {1}", "RESTAPI", 6)
});
document.Add(new Microsoft.VisualStudio.Services.WebApi.Patch.Json.JsonPatchOperation()
{
Path = "/fields/System.AreaPath",
Operation = Microsoft.VisualStudio.Services.WebApi.Patch.Operation.Add,
Value =string.Format("{0}\\{1}",teamProjectName, "SharedArea")
});
document.Add(
new Microsoft.VisualStudio.Services.WebApi.Patch.Json.JsonPatchOperation()
{
Path = "/fields/System.AssignedTo",
Operation = Microsoft.VisualStudio.Services.WebApi.Patch.Operation.Add,
Value = "[user account]"
});
document.Add(
new Microsoft.VisualStudio.Services.WebApi.Patch.Json.JsonPatchOperation()
{
Path = "/fields/System.Description",
Operation = Microsoft.VisualStudio.Services.WebApi.Patch.Operation.Add,
Value = "destest"
});
var workitem= workitemClient.CreateWorkItemAsync(document, teamProjectName, workitemtype).Result;

The method must be POST and Uri correct for consume the Api tfs is :
https://dev.azure.com/{organization}/{proyect}/_apis/wit/workitems/${type}?api-version=5.0
Check in :
https://learn.microsoft.com/en-us/rest/api/azure/devops/wit/work%20items/create?view=azure-devops-rest-5.0
The next code function for me.
static void Main(string[] args)
{
CreateWorkItem();
}
public static void CreateWorkItem()
{
string _tokenAccess = "************"; //Click in security and get Token and give full access https://azure.microsoft.com/en-us/services/devops/
string type = "Bug";
string organization = "type your organization";
string proyect = "type your proyect";
string _UrlServiceCreate = $"https://dev.azure.com/{organization}/{proyect}/_apis/wit/workitems/${type}?api-version=5.0";
dynamic WorkItem = new List<dynamic>() {
new
{
op = "add",
path = "/fields/System.Title",
value = "Sample Bug test"
}
};
var WorkItemValue = new StringContent(JsonConvert.SerializeObject(WorkItem), Encoding.UTF8, "application/json-patch+json");
var JsonResultWorkItemCreated = HttpPost(_UrlServiceCreate, _tokenAccess, WorkItemValue);
}
public static string HttpPost(string urlService, string token, StringContent postValue)
{
try
{
string request = string.Empty;
using (HttpClient httpClient = new HttpClient())
{
httpClient.DefaultRequestHeaders.Accept.Clear();
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(ASCIIEncoding.ASCII.GetBytes(string.Format("{0}:{1}", "", token))));
using (HttpRequestMessage httpRequestMessage = new HttpRequestMessage(new HttpMethod("POST"), urlService) { Content = postValue })
{
var httpResponseMessage = httpClient.SendAsync(httpRequestMessage).Result;
if (httpResponseMessage.IsSuccessStatusCode)
request = httpResponseMessage.Content.ReadAsStringAsync().Result;
}
}
return request;
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
}

Related

Unable to show Response Header data from Post call to a Textbox c#

I have create a c# custom application to create chat using one-on-one chat using user principal name. I want to show the response header into the Textbox when the user click the create button. I have follow the article below Get Response Header data from Post Call to get the response but currently I'm having some errors.
Coding part of Create Chat
private async void button2_Click(object sender, EventArgs e)
{
var scopes = new[] { "Directory.Read.All", "Directory.ReadWrite.All", "User.Read", "User.Read.All", "User.ReadBasic.All", "User.ReadWrite" };
{
// Multi-tenant apps can use "common",
// single-tenant apps must use the tenant ID from the Azure portal
var tenantId = "5exxxx3-376a-43b1-9xxx0c-ef3xxxf8bx0";
// Value from app registration
var clientId = "35xxx-5c92-4xxx9-8500-635xxxe8af";
// using Azure.Identity;
var options = new TokenCredentialOptions
{
AuthorityHost = AzureAuthorityHosts.AzurePublicCloud
};
var userName = "ng.xxxxxi.com";
var password = "Aaxxxxxx";
// https://learn.microsoft.com/dotnet/api/azure.identity.usernamepasswordcredential
var userNamePasswordCredential = new UsernamePasswordCredential(
userName, password, tenantId, clientId, options);
GraphServiceClient graphClient = new GraphServiceClient(userNamePasswordCredential, scopes);
var chat = new Chat
{
ChatType = ChatType.OneOnOne,
Members = new ChatMembersCollectionPage()
{
new AadUserConversationMember
{
Roles = new List<String>()
{
"owner"
},
AdditionalData = new Dictionary<string, object>()
{
{"user#odata.bind", "https://graph.microsoft.com/v1.0/users[comboBox2.Text]"}
}
},
new AadUserConversationMember
{
Roles = new List<String>()
{
"owner"
},
AdditionalData = new Dictionary<string, object>()
{
{"user#odata.bind", "https://graph.microsoft.com/v1.0/users/[comboBox3.Text]"}
}
}
}
};
var requestUrl = graphClient.Chats.Request().RequestUrl;
var content = "json_content";
var hrm = new HttpRequestMessage(HttpMethod.Post, requestUrl);
hrm.Content = new StringContent(content, System.Text.Encoding.UTF8, "aplication/json");
// Authenticate (add access token)
await graphClient.AuthenticationProvider.AuthenticateRequestAsync(hrm);
// Send the request and get the response.
var response = await graphClient.HttpProvider.SendAsync(hrm);
if (!response.IsSuccessStatusCode)
{
throw new ServiceException(
new Error
{
Code = response.StatusCode.ToString(),
Message = await response.Content.ReadAsStringAsync()
});
}
else
{
// read header values
var headerValues = response.Headers.GetValues(textBox2.Text);
}
await graphClient.Chats
.Request()
.AddAsync(chat);
}
}

Not getting folder id in response after creating folder to google drive by google api

I am using rest end point and don't get folder id on creation. It should be in response but not there.
Folder is getting created successfully.
url: https://www.googleapis.com/drive/v3/files
public static async void CreateFolder(string accessToken, string brandFolderName)
{
var gDriveItems = await GetFoldersByBrand(accessToken,brandFolderName);
if (gDriveItems.Any(x=>x.Name.ToLower() == brandFolderName.ToLower()))
{
return;
}
var request = new HttpRequestMessage(HttpMethod.Post, "drive/v3/files");
request.Headers.Add("Authorization", "Bearer "+ accessToken);
request.Headers.Add("Accept","application/json");
JsonObject jsonFolderObject = new JsonObject();
jsonFolderObject.Add("name", brandFolderName);
jsonFolderObject.Add("mimeType", "application/vnd.google-apps.folder");
var data = JsonConvert.SerializeObject(jsonFolderObject);
request.Content = new StringContent(data, Encoding.UTF8, "application/json");
var responce = await _httpClient.SendAsync(request);
var mm = responce.Content.ReadAsStringAsync();
responce.EnsureSuccessStatusCode();
}
For reference, here's my code to add a new folder.
I use Google.Apis.Drive.v3
service is an instance of DriveService with the relevant scope to create a folder/file.
This will give me the Id of the new folder in the result
private static async Task<File> CreateRankingsFolder(DriveService service,
string driveId,
string parentId,
string folderName = "YOURFOLDERNAME")
{
File result = null;
try
{
File body = new File();
body.Name = folderName;
body.MimeType = "application/vnd.google-apps.folder";
body.DriveId = driveId;
if (!string.IsNullOrEmpty(parentId))
{
var _parents = new List<string>()
{
parentId
};
body.Parents = _parents;
}
// service is an authorized Drive API service instance
var req = service.Files.Create(body);
result = await req.ExecuteAsync();
}
catch(Exception e)
{
}
return result;
}

Property folder in payload has a value that does not match schema Graph Api

the graph API request to create a folder in one drive is
POST /me/drive/root/children
Content-Type: application/json
{
"name": "New Folder",
"folder": { },
"#microsoft.graph.conflictBehavior": "rename"
}
this but i dont undestand how to pass " { } " in httprequest content body .
My code:
var tt = "{ }";
var jsonData = $#"{{ ""name"": ""{txtValue}"",""folder"":""{tt}""}}";
var body = new StringContent(jsonData, Encoding.UTF8,
"application/json");
apiRequest.Content = body;
apiRequest.Headers.Accept.Add(new
MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = await httpClient.SendAsync(apiRequest);
string d = response.Content.ReadAsStringAsync().Result.ToString();
but gives the error ""code": "BadRequest","message": "Property folder in payload has a value that does not match schema.","
Can anybody give me a hand ?
Any particular reason for not utilizing Microsoft Graph Client Library for .NET for that matter?
Anyway the following example demonstrates how to create a new folder in a drive via HttpClient:
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
client.BaseAddress = new Uri("https://graph.microsoft.com");
var folderPayload = new Dictionary<string, object>
{
["name"] = "Test Folder",
["folder"] = new { },
["#microsoft.graph.conflictBehavior"] = "rename"
};
var requestContent = new StringContent(JsonConvert.SerializeObject(folderPayload));
requestContent.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json");
var response = await client.PostAsync($"/v1.0/me/drive/root/children", requestContent);
var data = response.Content.ReadAsStringAsync().Result.ToString();
}

Error when using TFS API concerning updating work items( HTTP Status 400 )

I am trying to update a field of a work-item on TFS using the TFS API according to the Microsoft document. There is something wrong with the api "Update work items" when using the sample code listed on the page, the returning status code of the response is 400. No matter what I did, the status code is always 400, can anyone please give me some help?
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using Newtonsoft.Json;
public void UpdateWorkItemUpdateField()
{
string _personalAccessToken = "xxxxxxxxxxxxxx";
string _credentials = Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(string.Format("{0}:{1}", "", _personalAccessToken)));
string _id = "111";
Object[] patchDocument = new Object[3];
patchDocument[0] = new { op = "test", path = "/rev", value = "1" };
patchDocument[1] = new { op = "add", path = "/fields/Microsoft.VSTS.Common.Priority", value = "2" };
patchDocument[2] = new { op = "add", path = "/fields/System.History", value = "Changing priority" };
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", _credentials);
var patchValue = new StringContent(JsonConvert.SerializeObject(patchDocument), Encoding.UTF8, "application/json"); // mediaType needs to be application/json-patch+json for a patch call
var method = new HttpMethod("PATCH");
var request = new HttpRequestMessage(method, "https://accountname.visualstudio.com/_apis/wit/workitems/" + _id + "?api-version=2.2") { Content = patchValue };
var response = client.SendAsync(request).Result;
if (response.IsSuccessStatusCode)
{
var result = response.Content.ReadAsStringAsync().Result;
}
}
}
You are using a wrong mediaType, it should be 'application/json-patch+json' not 'application/json'.
var patchValue = new StringContent(JsonConvert.SerializeObject(patchDocument), Encoding.UTF8, "application/json-patch+json");
In the code sample, it has already noted you:
// mediaType needs to be application/json-patch+json for a patch call
You're invoke a Patch call, so please change the mediaType to application/json-patch+json.

O365 Create Events using REST API

I am trying to call this code
string accessToken = #".."; //valid token with right scopes
public string EventsUrl = #"https://outlook.office.com/api/v2.0/me/events";
// generate body
var postBody = JsonBody(invite);
using (var client = new HttpClient())
{
using (var request = new HttpRequestMessage(HttpMethod.Post, EventsUrl))
{
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
var content = new StringContent(postBody, Encoding.UTF8, "application/json");
request.Content = content;
var response = await client.SendAsync(request);
return (response.IsSuccessStatusCode);
}
}
The method that create JsonBody is,
public string JsonBody(User user, Session session){
var invite = new EventInvite
{
Attendees = new Attendee[1]
};
invite.Attendees[0] = new Attendee
{
Type = "Required",
EmailAddress = new Emailaddress { Name = user.GetName(), Address = user.GetEmail() }
};
invite.Start = new Start { DateTime = session.DateTime_Start };
invite.End = new End { DateTime = session.DateTime_Start.AddMinutes(15) };
invite.Subject = session.Name;
invite.Body = new Body { ContentType = "HTML", Content = $"Some Content" };
return JsonConvert.SerializeObject(eventInvite);
}
I am getting a Bad Request as response. Is there any alternative to build an Event? I want this code to be very thin as this is accessed in non UI based application
What is the best way to create Calendar Event?
The fix involves setting up the Timezone in the Start and End
string timeZone="Singapore Standard Time";
invite.Start = new Start { DateTime = session.DateTime_Start, TimeZone = timeZone };
invite.End = new End { DateTime = session.DateTime_Start.AddMinutes(60), TimeZone = timeZone };
var postBody = JsonConvert.SerializeObject(invite, Formatting.Indented);

Categories

Resources