Xamarin - C# - HttpClient - post

I have a question regarding httpclient, i have a node.js rest api and Im trying to post (send) the user info to the service in order to insert to a database. the service is ok i tested manually and with postman.
But im using vs2017 xamarin and to consume the information im using the httpclient
I convert my user object to a json format
var json = JsonConvert.SerializeObject(user);
result: {"userName":"user","email":"user#hot.com","psw":"jok"}
then I create a content string type and pass the json:
var content = new StringContent(json, Encoding.UTF8, "application/json");
then I create the client
var client = new HttpClient();
and i test the following two codes
if i use this code the service work and the data is inserted in the data base but i think is because im like manually passing the parameters
HttpResponseMessage response = await client.PostAsync("http://localhost/ws/postUser/"+ e.userName + "/" + e.email + "/" + e.psw, content);
but what i was expecting is that this code works but in the server im getting the error that the url is not find. I think i need to map the parameters with the content
HttpResponseMessage response = await client.PostAsync("http://localhost/ws/postUser/", content);
The URL of the service is
http://localhost/ws/postUser/:userName/:email/:psw
this is the complete code:
I have a OnSignUpEventArgs class that inherit from EventArgs and where i declare the user object.
private async void SigUpDialog_mOnSigUpComplete(object sender, OnSignUpEventArgs e)
{
var json = JsonConvert.SerializeObject(e);
var content = new StringContent(json, Encoding.UTF8, "application/json");
var client = new HttpClient();
HttpResponseMessage response = await client.PostAsync("http://localhost/ws/postGasUser/"+ e.userName + "/" + e.email + "/" + e.psw, content);
// HttpResponseMessage response = await client.PostAsync("http://localhost/ws/postGasUser/", content);
if (response.IsSuccessStatusCode)
{
Console.Write("Success");
}
else
{
Console.Write("Error");
}
}

Related

c# - TFS 2015 Service hook to post HTTP call to Slack

Have been working on creating a custom TFS Service Hook which 'll post (HTTP) notification to Slack.
My requirement is to POST a HTTP call to slack when a Bug workitem's status is changed to Inprogress . (I have Implemented the same with TFS Server side plugin .unfortunately , I had to go for Service Hook over Plugin)
I tried the below code with TFS 2017 onprem with PAT, unfortunately it was breaking. am I doing anything wrong ? I want my code to work in 2015.2 without PAT.
Can someone help please ?
public async static void CreateServiceHook(string collName, string projName, string projId, string AccessToken)
{
try
{
using (HttpClient client = new HttpClient())
{
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", AccessToken);
string url = "https://" + collName + ".visualstudio.com/DefaultCollection/_apis/projects/" + projName + "?includecapabilities=true&api-version=1.0";
HttpRequestMessage req = new HttpRequestMessage(new HttpMethod("GET"), url);
var response = client.SendAsync(req).Result;
string contents = await response.Content.ReadAsStringAsync();
}
//create service hook
using (HttpClient client = new HttpClient())
{
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", AccessToken);
var request = new
{
publisherId = "tfs",
eventType = "workitem.created",
consumerId = "webHooks",
consumerActionId = "httpRequest",
scope = "project",
publisherInputs = new {
// buildStatus = "",
projectId = projId
},
consumerInputs = new
{
url = "https://slack.api.com/services/XXXXXXXXXX
}
};
var response = client.PostAsync("https://" + collName + ".visualstudio.com/DefaultCollection/_apis/hooks/subscriptions/?api-version=1.0",
new StringContent(JsonConvert.SerializeObject(request).ToString(),
Encoding.UTF8, "application/json"))
.Result;
if (response.IsSuccessStatusCode)
{
dynamic content = JsonConvert.DeserializeObject(
response.Content.ReadAsStringAsync()
.Result);
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
TFS has default slack service hook which can post a message to a channel. So instead of using web hooks consumer, you can use slack consumer. And you can only achieve is posting messages to Slack when a Bug workitem's status is updated.
The API looks like below:
POST http://tfsserver:8080/tfs/DefaultCollection/_apis/hooks/subscriptions?api-version=3.2
Content-Type: application/json
{
"consumerActionId":"postMessageToChannel",
"consumerId":"slack",
"consumerInputs":{
"url":"https://hooks.slack.com/services/xxxxxx"},
"eventType":"workitem.updated",
"publisherId":"tfs",
"publisherInputs":{
"areaPath":"",
"workItemType":"Bug",
"changedFields":"System.State",
"projectId":"77e3c775-dc30-4354-xxxx-xxxxxxxxxxxx"},
"scope":1
}

Sample Webapi to trigger TFS rest services & post HTTP calls

I have been working on a requirement, i.e. when a bug is created/inprogress in TFS post a HTTP call to Slack (third party collaboration tool).
When a bug is closed post one more HTTP call to Slack.
I had implemented TFS server side plugin, unfortunately we don't have complete access to TFS and cannot implement. So, planning to implement Webapi and host it (say in Docker container) and whenever bug created / closed event happens in TFS it should post HTTP call.
I have created a simple console app with a method and it's working fine.
any sample code or thoughts to convert it to web api?
if I host, can it monitor TFS events and posts some HTTP calls?
public class GetWI
{
static void Main(string[] args)
{
GetWI ex = new GetWI();
ex.GetWorkItemsByWiql();
}
public void GetWorkItemsByWiql()
{
string _personalAccessToken = "xxxx";
string _credentials = Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(string.Format("{0}:{1}", "", _personalAccessToken)));
//this is needed because we want to create a project scoped query
string project = "Agileportfolio";
//create wiql object
var wiql = new
{
query = "Select [State], [Title] " +
"From WorkItems " +
"Where [Work Item Type] = 'Bug' " +
"And [System.TeamProject] = '" + project + "' " +
"And [System.State] = 'New' " +
"Order By [State] Asc, [Changed Date] Desc"
};
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("https://test.visualstudio.com");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", _credentials);
//serialize the wiql object into a json string
var postValue = new StringContent(JsonConvert.SerializeObject(wiql), Encoding.UTF8, "application/json"); //mediaType needs to be application/json for a post call
var method = new HttpMethod("POST");
var httpRequestMessage = new HttpRequestMessage(method, "https://abrahamdhanyaraj.visualstudio.com/_apis/wit/wiql?api-version=2.2") { Content = postValue };
var httpResponseMessage = client.SendAsync(httpRequestMessage).Result;
if (httpResponseMessage.IsSuccessStatusCode)
{
WorkItemQueryResult workItemQueryResult = httpResponseMessage.Content.ReadAsAsync<WorkItemQueryResult>().Result;
//now that we have a bunch of work items, build a list of id's so we can get details
var builder = new System.Text.StringBuilder();
foreach (var item in workItemQueryResult.WorkItems)
{
builder.Append(item.Id.ToString()).Append(",");
}
//clean up string of id's
string ids = builder.ToString().TrimEnd(new char[] { ',' });
HttpResponseMessage getWorkItemsHttpResponse = client.GetAsync("_apis/wit/workitems?ids=" + ids + "&fields=System.Id,System.Title,System.State&asOf=" + workItemQueryResult.AsOf + "&api-version=2.2").Result;
if (getWorkItemsHttpResponse.IsSuccessStatusCode)
{
var result = getWorkItemsHttpResponse.Content.ReadAsStringAsync().Result;
//Read title
}
}
// Create Channel
string name = "xyzz3";
var payload = new
{
token = "xoxp-291239704800-292962676087-297314229698-a80e720d98e443c8afb0c4cb2c09e745",
name = "xyzz3",
};
var serializedPayload = JsonConvert.SerializeObject(payload);
var response = client.PostAsync("https://slack.com/api/channels.create" + "?token=test&name=" + name + "&pretty=1",
new StringContent(serializedPayload, Encoding.UTF8, "application/json")).Result;
if (response.IsSuccessStatusCode)
{
dynamic content = JsonConvert.DeserializeObject(
response.Content.ReadAsStringAsync()
.Result);
}
}
}
I use wcf service to listen events from TFS. You may find my project here: https://github.com/ashamrai/tfevents
For wcf service:
Update your ServiceName.svc file and add:
Factory="System.ServiceModel.Activation.WebServiceHostFactory"
Create web method to use json:
[OperationContract]
[WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Bare)]
void WorkItemChangedEvent(Stream EventData);
Convert stream with Newtonsoft.Json to get information about event and work item:
StreamReader _reader = new StreamReader(pEventData, Encoding.UTF8);
string _eventStr = _reader.ReadToEnd();
WorkItemEventCore _wieventcorre = JsonConvert.DeserializeObject(_eventStr);
Then you have to create the subscription with url "http://host:port/service.svc/webmethod": https://learn.microsoft.com/en-us/vsts/service-hooks/services/webhooks
Instead of using a query and manually polling Visual Studio Team Services (VSTS), you can use a concept called WebHooks. You configure a WebHook in VSTS to listen for events and send these to a public endpoint. One event type is for Work Items. The endpoint can be any type of public endpoint, for example an Azure Function.
If the only thing you want to do is post the events to Slack, it's even easier because that's a standard integration point: Slack with VSTS.
This is much easier then using a server side plugin or writing your own Web API.

"Response status code does not indicate success: 500 (Internal Server Error)" while creating Test Suite through TFS Rest API

While trying to create a Test Suite using TFS 2017 REST API, I am getting the error:
System.Net.Http.HttpRequestException - Response status code does not
indicate success: 500 (Internal Server Error)
Code I tried:
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
string base64StringPat = Convert.ToBase64String(ASCIIEncoding.ASCII.GetBytes(string.Format("{0}:{1}", "", Configs.Pat)));
AuthenticationHeaderValue authHeader = new AuthenticationHeaderValue("Basic", base64StringPat);
client.DefaultRequestHeaders.Authorization = authHeader;
string url = "http://vmctp-tl-mtm:8080/tfs/DefaultCollection/SgkProject/_apis/test/Plans/7/Suites/8?api-version=1.0";
var content = new StringContent("{\"suiteType\":\"StaticTestSuite\",\"name\":\"Module1\"}", Encoding.UTF8, "application/json");
using (HttpResponseMessage response = client.PostAsync(url, content).Result)
{
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseBody);
}
}
I have used this documentation from Microsoft to call the API: Create a test suite
Please guide me in fixing the issue.
HTTP code 500 means that this is an error on your server. The server threw an exception when trying to process this POST request.
So, this error has nothing to do with HttpClient. Just check your server first and see what causes the exception.
A possibility is that the specified content type is not expected by the server. POST a StringContent will set the content type to text/plain. You might find the server doesn't like that. In this case just try to find out what media type the server is expecting and set the Headers.ContentType of the StringContent instance.
Whatever, I can create the suite by below sample, you can have a try for that:
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
namespace CreateTestSuite
{
class Program
{
public static void Main()
{
Task t = CreateTestSuite();
Task.WaitAll(new Task[] { t });
}
private static async Task CreateTestSuite()
{
try
{
var username = "username";
var password = "password";
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Accept.Add(
new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic",
Convert.ToBase64String(
System.Text.ASCIIEncoding.ASCII.GetBytes(
string.Format("{0}:{1}", username, password))));
string url = "http://server:8080/tfs/DefaultCollection/LCScrum/_apis/test/plans/212/suites/408?api-version=1.0";
var content = new StringContent("{\"suiteType\":\"StaticTestSuite\",\"name\":\"Module3\"}", Encoding.UTF8, "application/json");
using (HttpResponseMessage response = client.PostAsync(url, content).Result)
{
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseBody);
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
}
}

Xamarin__HttpClient__HttpResponseMessage-Content --- Getting HTML instead of JSON

HttpClient myClient = new HttpClient();
myClient.BaseAddress = new Uri(URL);
Base address already specified on client it's URL.
var encodedObject = JsonConvert.SerializeObject(Obj);
myClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = await myClient.PostAsync("test.php/yourAPI",new StringContent(encodedObject, System.Text.Encoding.UTF8, "application/json"));
if (response.IsSuccessStatusCode)
{
var responseContent = response.ToString();
var responsebody = response.Content.ToString();
Stream receiveStream = response.GetResponseStream();
string responseBodyAsText = response.Content.ReadAsStringAsync().Result;
}
Could be a content negotiation issue. Try clearing the Accept header before adding the json media type
myClient.DefaultRequestHeaders.Accept.Clear();
myClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
//...other code removed for brevity.
this code sets the Accept header to "application/json", which tells the server to send data in JSON format.
Reference source: Calling a Web API From a .NET Client in ASP.NET Web API 2
the Method PostAsync has as first argument the complete URI of The API. Therefore, it should be like follow :
HttpResponseMessage response = await myClient.PostAsync("http://bla-bla-bla/test.php/test",new StringContent(encodedObject, System.Text.Encoding.UTF8, "application/json"));
And there is no need to define the BaseAddress.

JIRA rest api to fetch the activity stream

I am trying to get activity stream of my jira instance using the below api and it is not working , can anybody point me in the right direction ?
You should check this page out: https://developer.atlassian.com/docs/atlassian-platform-common-components/activity-streams/consuming-an-activity-streams-feed
The Atom feed of the activity stream works well only if you also log in in your feed reader.
Here is an example of consuming the activity stream through the Jira API using Basic Authentication. This is in C#, but the basic pattern can be applied anywhere:
string myJiraUsername = "username";
string myJiraPassword = "password"; //or API token
string authenticationHeaderValue = Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(myJiraUsername + ":" + myJiraPassword));
System.Net.Http.HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", authenticationHeaderValue);
Task<HttpResponseMessage> task = client.GetAsync("https://mycompany.atlassian.net/activity");
task.Wait();
HttpResponseMessage response = task.Result;
string resultOfApiCall = "";
if (response.IsSuccessStatusCode)
{
resultOfApiCall = response.Content.ReadAsStringAsync().Result;
Console.WriteLine("This was returned by your API request:\n" + resultOfApiCall);
}

Resources