I am beginner in using this api and it's services. I have tried lots of thing but nothing worked for me, Just wanted to push silent notification. Any suggestion will be appreciated and Thanks in advance.
private static readonly string oneSignalUrl = "https://onesignal.com/api/v1/notifications";
public async Task<HttpResponseMessage> SendNotification(string playerId, string notificationAppId, string notificationSecretKey)
{
var client = new HttpClient();
client.BaseAddress = new Uri(oneSignalUrl);
client.DefaultRequestHeaders.Add("authorization", "Basic " + notificationSecretKey);
var model = new DictionaryDTO { aps = new Dictionary<string, int>() { { "content-available", 1 } }, acme1 = "logout" };
var content = GetContent(notificationAppId, model, playerId);
var response = await client.PostAsync(oneSignalUrl, content);
return response;
}
public StringContent GetContent(string notificationAppId, DictionaryDTO model, string playerId)
{
var content = new StringContent(JsonConvert.SerializeObject(new
{
app_id = notificationAppId,
contents = new
{
en = "Testing the push notification functionality",
model
},
include_player_ids = new string[] { playerId }
}), Encoding.UTF8, "application/json");
return content;
}
Related
I am new to RestAPI and am not sure how to call one and pass it credentials. I have a Windows Forms with a "POST" button. This project is built using .Net framework 4.5. When user clicks on this button it executes code with the class below. In this calls there is a Post method that calls a RestAPI. This RestApi requires basic authentication. Any help would be great.
public static class CallRestAPI
{
private static readonly string baseURL = "https://servername/fscmRestApi/resources/11.13.18.05/erpintegrations";
public static async Task<string> Post(string name, string job)
{
var inputData = new Dictionary<string, string>
{
{"name", name },
{"job", job }
};
var input = new FormUrlEncodedContent(inputData);
using (HttpClient client = new HttpClient())
{
using (HttpResponseMessage res = await client.PostAsync(baseURL + "users", input))
{
using (HttpContent content = res.Content)
{
string data = await content.ReadAsStringAsync();
if (data != null)
{
return data;
}
}
}
}
return string.Empty;
}
}
You have to add the authorization header:
var byteArray = Encoding.ASCII.GetBytes($"{UserName}:{Password}");
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray));
I am having trouble inserting data into a MongoDB from a windows form application through a rest API. Below is what I have so far.
ProductController (API)
[HttpPost]
public JsonResult Post(Product item)
{
MongoClient dbClient = new MongoClient(_configuration.GetConnectionString("AppConString"));
dbClient.GetDatabase("motopartsdb").GetCollection<Product>("products").InsertOne(item);
return new JsonResult("Added Successfully");
}
WindowsApplication
async private void createProduct()
{
var values = new Dictionary<string, string>
{
{ "name", ProductNameInput.Text },
{ "category", category},
{ "type", "New" },
{ "supplier", SupplierInput.Text },
{ "quantity", QuantityInput.Text },
{ "price", PriceInput.Text },
{ "condition", "" },
{ "description", DescriptionInput.Text }
};
HttpClient client = new HttpClient();
var content = new FormUrlEncodedContent(values);
var response = await client.PostAsync("https://localhost:57501/api/product", content);
var responseString = await response.Content.ReadAsStringAsync();
}
When I run the code I get error 415 from the rest API, I tried possible fixes but cant seem to figure it out.
Any help is appreciated, many thanks.
I would recommend that you don't send a Dictionary<string, string> but a Product object.
Below is an untested example, I am guessing your Product object properties.
EDITED
I have edited the below code to Serialize the product and generated StringContent to send.
async private void createProduct()
{
Product prod = new Product()
{
Name = ProductNameInput.Text,
Category = category,
Type = "New" ,
Supplier = SupplierInput.Text ,
Quantity = QuantityInput.Text ,
Price = PriceInput.Text ,
Condition = "" ,
Description = DescriptionInput.Text
};
HttpClient client = new HttpClient();
StringContent stringContent = null;
if (prod != null)
{
//serialize object to string in Json format
string content = JsonConvert.SerializeObject(prod, _jsonSerializerSettings);
//create content
stringContent = new StringContent(content, Encoding.UTF8, "application/json");
stringContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
}
var response = await client.PostAsync("https://localhost:57501/api/product", stringContent);
var responseString = await response.Content.ReadAsStringAsync();
}
In addition you may need to
add a JSON request header to your HttpClient
set your Mongo DB Convention. For example I use Camel Case.
//clear accept headers
client.DefaultRequestHeaders.Accept.Clear();
//add accept json
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
//an example C# object
public class MyExample
{
//camel case in mongoDB saved as firstName
public string FirstName {get; set;}
}
//on Mongo DB create
var camelCaseConvention = new ConventionPack { new CamelCaseElementNameConvention() };
ConventionRegistry.Register("CamelCase", camelCaseConvention, type => true);
I need to post data with files but I face this problem - all data is null.
It works when I use postman:
My post function in ASP.NET Core Web API:
public async Task<ActionResult<Category>> PostCategory([FromForm]CategoryViewModel model)
{
Category category = new Category()
{
Brief = model.Brief,
Color = model.Color,
IsDraft = model.IsDraft,
Name = model.Name,
Priority = model.Priority,
Update = DateTime.Now
};
if (model.Files != null)
{
category.IconUrl = ApplicationManager.UploadFiles(model.Files, "content/category")[0];
}
_context.Categories.Add(category);
await _context.SaveChangesAsync();
return CreatedAtAction("GetCategory", new { id = category.Id }, category);
}
My post function in ASP.NET Core MVC:
private ApiClient _client;
_client = new ApiClient(new Uri("https:localhost:55436/api/"));
public async Task<IActionResult> Create([FromForm]CategoryViewModel category)
{
var uri = new Uri(_appSettings.WebApiBaseUrl + "Categories");
var response = await _client.PostAsync<Category, CategoryViewModel>(uri, category);
return RedirectToAction("index");
}
My ApiClient class:
public partial class ApiClient
{
private readonly HttpClient _httpClient;
private Uri BaseEndpoint { get; set; }
public ApiClient(Uri baseEndpoint)
{
if (baseEndpoint == null)
{
throw new ArgumentNullException("baseEndpoint");
}
BaseEndpoint = baseEndpoint;
_httpClient = new HttpClient();
}
/// <summary>
/// Common method for making GET calls
/// </summary>
public async Task<T> GetAsync<T>(Uri requestUrl)
{
addHeaders();
var response = await _httpClient.GetAsync(requestUrl, HttpCompletionOption.ResponseHeadersRead);
response.EnsureSuccessStatusCode();
var data = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<T>(data);
}
public async Task<HttpResponseMessage> PostStreamAsync(Uri requestUrl, object content)
{
using (var client = new HttpClient())
using (var request = new HttpRequestMessage(HttpMethod.Post, requestUrl))
using (var httpContent = CreateHttpContentForStream(content))
{
request.Content = httpContent;
using (var response = await client
.SendAsync(request, HttpCompletionOption.ResponseHeadersRead)
.ConfigureAwait(false))
{
response.EnsureSuccessStatusCode();
return response;
}
}
}
public async Task<HttpResponseMessage> PostBasicAsync(Uri requestUrl, object content)
{
using (var client = new HttpClient())
using (var request = new HttpRequestMessage(HttpMethod.Post, requestUrl))
{
var json = JsonConvert.SerializeObject(content);
using (var stringContent = new StringContent(json, Encoding.UTF8, "application/json"))
{
request.Content = stringContent;
using (var response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead)
.ConfigureAwait(false))
{
response.EnsureSuccessStatusCode();
return response;
}
}
}
}
public static void SerializeJsonIntoStream(object value, Stream stream)
{
using (var sw = new StreamWriter(stream, new UTF8Encoding(false), 1024, true))
using (var jtw = new JsonTextWriter(sw) { Formatting = Formatting.None })
{
var js = new JsonSerializer();
js.Serialize(jtw, value);
jtw.Flush();
}
}
private static HttpContent CreateHttpContentForStream<T>(T content)
{
HttpContent httpContent = null;
if (content != null)
{
var ms = new MemoryStream();
SerializeJsonIntoStream(content, ms);
ms.Seek(0, SeekOrigin.Begin);
httpContent = new StreamContent(ms);
httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
}
return httpContent;
}
/// <summary>
/// Common method for making POST calls
/// </summary>
public async Task<T> PostAsync<T>(Uri requestUrl, T content)
{
addHeaders();
var response = await _httpClient.PostAsync(requestUrl.ToString(), CreateHttpContent<T>(content));
response.EnsureSuccessStatusCode();
var data = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<T>(data);
}
public async Task<T1> PostAsync<T1, T2>(Uri requestUrl, T2 content)
{
addHeaders();
var response = await _httpClient.PostAsync(requestUrl.ToString(), CreateHttpContent<T2>(content));
response.EnsureSuccessStatusCode();
var data = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<T1>(data);
}
public Uri CreateRequestUri(string relativePath, string queryString = "")
{
var endpoint = new Uri(BaseEndpoint, relativePath);
var uriBuilder = new UriBuilder(endpoint);
uriBuilder.Query = queryString;
return uriBuilder.Uri;
}
public HttpContent CreateHttpContent<T>(T content)
{
var json = JsonConvert.SerializeObject(content, MicrosoftDateFormatSettings);
var value = new StringContent(json, Encoding.UTF8, "application/json");
return value;
}
public static JsonSerializerSettings MicrosoftDateFormatSettings
{
get
{
return new JsonSerializerSettings
{
DateFormatHandling = DateFormatHandling.MicrosoftDateFormat
};
}
}
public void addHeaders()
{
_httpClient.DefaultRequestHeaders.Remove("userIP");
_httpClient.DefaultRequestHeaders.Add("userIP", "192.168.1.1");
}
}
If you want to post the multipart/form-data using HttpClient, you should write a separate post method using MultipartFormDataContent as HttpContent type as shown:
PostCategoryAsync
public async Task<Category> PostCategoryAsync(Uri requestUrl, CategoryViewModel content)
{
addHeaders();
var response = new HttpResponseMessage();
var fileContent = new StreamContent(content.Files.OpenReadStream())
{
Headers =
{
ContentLength = content.Files.Length,
ContentType = new MediaTypeHeaderValue(content.Files.ContentType)
}
};
var formDataContent = new MultipartFormDataContent();
formDataContent.Add(fileContent, "Files", content.Files.FileName); // file
//other form inputs
formDataContent.Add(new StringContent(content.Name), "Name");
formDataContent.Add(new StringContent(content.Brief), "Brief");
formDataContent.Add(new StringContent(content.IsDraft.ToString()), "IsDraft");
formDataContent.Add(new StringContent(content.Color), "Color");
formDataContent.Add(new StringContent(content.Priority), "Priority");
response = await _httpClient.PostAsync(requestUrl.ToString(), formDataContent);
var data = await response.Content.ReadAsStringAsync();
response.EnsureSuccessStatusCode();
return JsonConvert.DeserializeObject<Category>(data);
}
MVC controller
var response = await _client.PostCategoryAsync(uri, category);
Web API
I'm trying to do a patch http request to change one of the fields in TFS through the TFS REST API. I've tried several approaches, but I always end up with 400 error. Here is what I have right now:
public void SetFieldValue(string value, string path, int id)
{
var httpWebRequest = (HttpWebRequest)WebRequest.Create(PatchwebAPIUrl("wit/workitems", id.ToString()));
httpWebRequest.ContentType = "application/json-patch+json";
httpWebRequest.Method = "PATCH";
httpWebRequest.Headers["Authorization"] = "Basic" + Base64authorizationToken();
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
string json = "[{\"op\":\"replace\"," +
$"\"path\":\"{path}\"," +
$"\"value\":\"{value}\"}}]";
streamWriter.Write(JsonConvert.SerializeObject(json));
streamWriter.Flush();
streamWriter.Close();
}
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var result = streamReader.ReadToEnd();
}
}
And the test method that calls this method:
[TestMethod()]
public void setFieldValue()
{
TFSWebAPIImplementation webAPI = new TFSWebAPIImplementation();
webAPI.SetFieldValue("654321", "/fields/Custom.Tracking", 61949);
}
The PatchwebAPIUrl("...") Method is fine, and returns a good URL, when I navigate to it I get the JSON data that I want to edit. I'm not 100% on the path variable but it's used the same as the example provided from Microsoft. The authorization works, just based on the fact that when I mess with it I get a 401 instead.
This is my sample code:
Class for work item:
public class WorkItemAtrr
{
[JsonProperty("id")]
public int id;
[JsonProperty("rev")]
public int rev;
[JsonProperty("fields")]
public Dictionary<string, string> fields;
[JsonProperty("_links")]
public Dictionary<string, Link> _links;
[JsonProperty("relations")]
public List<Relation> relations;
[JsonProperty("url")]
public string url;
}
public class Link
{
[JsonProperty("href")]
public string href;
}
public class Relation
{
[JsonProperty("rel")]
public string rel;
[JsonProperty("url")]
public string url;
[JsonProperty("attributes")]
public RelationAttribute attributes;
}
public class RelationAttribute
{
[JsonProperty("comment")]
public string comment = "";
[JsonProperty("isLocked")]
public bool isLocked;
}
Class for new and updated fields:
public class NewField
{
[JsonProperty("op")]
public string op = "add";
[JsonProperty("path")]
public string path;
[JsonProperty("value")]
public object value;
}
Class for exceptions:
public class RestApiExceptionContainer
{
[JsonProperty("id")]
public int id;
[JsonProperty("innerException")]
public string innerException;
[JsonProperty("message")]
public string message;
[JsonProperty("typeName")]
public string typeName;
[JsonProperty("typeKey")]
public string typeKey;
[JsonProperty("errorCode")]
public int errorCode;
[JsonProperty("evenId")]
public int eventId;
}
Method for update a work item:
private static WorkItemAtrr UpdateWorkItemRest()
{
Dictionary<string, string> _fields = new Dictionary<string, string>();
_fields.Add("REFERENCE_NAME", "VALUE");
var _updatedWi = UpdateWorkItem("ID", _fields).Result;
}
Method for preparing request:
public async Task<WorkItemAtrr> UpdatedWorkItem(int pId, Dictionary<String, String> pFields)
{
//PATCH https://{instance}/DefaultCollection/_apis/wit/workitems/{id}?api-version={version}
string _query_url = String.Format("https://YOUR_SERVER/DefaultCollection/_apis/wit/workitems/{id}?api-version=1.0", pId);
List<Object> flds = new List<Object>();
foreach (var _key in pFields.Keys)
flds.Add(new NewField { op = "add", path = "/fields/" + _key, value = pFields[_key] });
HttpResponseMessage _response = await DoRequest(_query_url, JsonConvert.SerializeObject(flds), ClientMethod.PATCH);
return JsonConvert.DeserializeObject<WorkItemAtrr>(await ProcessResponse(_response));
}
Universal method for request:
private async Task<HttpResponseMessage> DoRequest(string pRequest, string pBody, ClientMethod pClientMethod)
{
try
{
HttpClientHandler _httpclienthndlr = new HttpClientHandler();
//update for your auth
if (UseDefaultCredentials) _httpclienthndlr.Credentials = CredentialCache.DefaultCredentials;
else if (TFSDomain == "") _httpclienthndlr.Credentials = new NetworkCredential(TFSUserName, TFSPassword);
else _httpclienthndlr.Credentials = new NetworkCredential(TFSUserName, TFSPassword, TFSDomain);
using (HttpClient _httpClient = new HttpClient(_httpclienthndlr))
{
switch (pClientMethod)
{
case ClientMethod.GET:
return await _httpClient.GetAsync(pRequest);
case ClientMethod.POST:
return await _httpClient.PostAsync(pRequest, new StringContent(pBody, Encoding.UTF8, "application/json"));
case ClientMethod.PATCH:
var _request = new HttpRequestMessage(new HttpMethod("PATCH"), pRequest);
_request.Content = new StringContent(pBody, Encoding.UTF8, "application/json-patch+json");
return await _httpClient.SendAsync(_request);
default:
return null;
}
}
}
catch (Exception _ex)
{
throw new Exception("Http Request Error", _ex);
}
}
Universal method for response:
public async Task<string> ProcessResponse(HttpResponseMessage pResponse)
{
string _responseStr = "";
if (pResponse != null)
{
if (pResponse.IsSuccessStatusCode)
_responseStr = await pResponse.Content.ReadAsStringAsync();
else
{
_responseStr = await pResponse.Content.ReadAsStringAsync();
var _error = JsonConvert.DeserializeObject<RestApiExceptionContainer>(_responseStr);
throw new RestApiException(_error);
}
}
return _responseStr;
}
A 400 means that the request was malformed. In other words, the data stream sent by the client to the server didn't follow the rules.
In the case of a REST API with a JSON payload, 400's are typically, used to indicate that the JSON is invalid in some way according to the API specification for the service.
So, the issue is caused by the JSON body.
Just try it like below:
string json = "[{\"op\":\"replace\",\"path\":\"/fields/System.Title\",\"value\":\"Title\"}]";
You can also use below sample to update the fields with PATCH method via the REST API, it works for me:
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using Newtonsoft.Json;
namespace UpdateWorkItemFiled0411
{
class Program
{
static void Main(string[] args)
{
string password = "xxxx";
string credentials = Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(string.Format("{0}:{1}", "username", password )));
Object[] patchDocument = new Object[1];
patchDocument[0] = new { op = "replace", path = "/relations/attributes/comment", value = "Adding traceability to dependencies" };
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, "http://server:8080/tfs/DefaultCollection/_apis/wit/workitems/21?api-version=1.0") { Content = patchValue };
var response = client.SendAsync(request).Result;
if (response.IsSuccessStatusCode)
{
var result = response.Content.ReadAsStringAsync().Result;
}
}
}
}
}
Also you may use nugate package Microsoft.TeamFoundationServer.Client.
Connect to team project from here:
using Microsoft.TeamFoundation.Core.WebApi;
using Microsoft.VisualStudio.Services.Common;
...
//create uri and VssBasicCredential variables
Uri uri = new Uri(url);
VssBasicCredential credentials = new VssBasicCredential("", personalAccessToken);
using (ProjectHttpClient projectHttpClient = new ProjectHttpClient(uri, credentials))
{
IEnumerable<TeamProjectReference> projects = projectHttpClient.GetProjects().Result;
}
my code to add comments:
JsonPatchDocument PatchDocument = new JsonPatchDocument();
PatchDocument.Add(
new JsonPatchOperation()
{
Operation = Operation.Add,
Path = "/fields/System.History",
Value = "Changes from script"
}
);
VssCredentials Cred = new VssCredentials(true);
WorkItemTrackingHttpClient WIClient = new WorkItemTrackingHttpClient(new Uri("http://YOUR_SERVER/tfs/DefaultCollection"), Cred);
WorkItem result = WIClient.UpdateWorkItemAsync(PatchDocument, id).Result;
Okay guys, so unfortunately none of your solutions worked, and I think it's because there was always an extra set of curly brackets on the outside that the TFS API didn't like. Here is my solution that solved my problem:
public void SetFieldValue(string value, string path, int id)
{
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", Base64authorizationToken());
StringBuilder sb = new StringBuilder();
StringWriter sw = new StringWriter(sb);
using (JsonWriter writer = new JsonTextWriter(sw))
{
writer.Formatting = Formatting.Indented;
writer.WriteStartArray(); // [
writer.WriteStartObject(); // {
writer.WritePropertyName("op"); // "Product:"
writer.WriteValue("replace");
writer.WritePropertyName("path");
writer.WriteValue(path);
writer.WritePropertyName("value");
writer.WriteValue(value);
writer.WriteEndObject(); //}
writer.WriteEnd(); // ]
}
var method = new HttpMethod("PATCH");
var request = new HttpRequestMessage(method, PatchwebAPIUrl("wit/workitems", id.ToString())) { Content = new StringContent(sb.ToString().Trim(new char[] {'{','}'}), Encoding.UTF8, "application/json-patch+json") };
var response = client.SendAsync(request).Result;
if (response.IsSuccessStatusCode)
{
var result = response.Content.ReadAsStringAsync().Result;
}
}
}
i use asp.net mvc and c#,
i my bank setion project i use this code for banking
var requestContent = new FormUrlEncodedContent(new[] {
new KeyValuePair<string, string>("amount", payment.Amount), //i want change this section for <string,int>
new KeyValuePair<string, string>("transid", "id"),
new KeyValuePair<string, string>("pin","pin" )
});
var client = new HttpClient();
HttpResponseMessage response = await client.PostAsync("http://address.com/api/verify/", requestContent);
HttpContent responseContent = response.Content;
string result = "";
using (var reader = new StreamReader(await responseContent.ReadAsStreamAsync()))
{
result = await reader.ReadToEndAsync();
}
now my bank scenario is change and i should pass integer for amount,how i can do i from mycode?
because FormUrlEncodedContent accept <string,string>
thank you for your help
Try this, It is working for me.
public class PaymentActionsRequest
{
[JsonProperty("payment_intent")]
public string PaymentIntent { get; set; }
[JsonProperty("amount")]
public long Amount { get; set; }
}
var keyValueContent = PaymentActionsRequest.ToKeyValue();
var formUrlEncodedContent = new FormUrlEncodedContent(keyValueContent);
You need to use something like Amount.ToString() as this content would eventually be string/encoded as part of POST body.