openrouteservice API - "error": "Authorization field missing" - c#

I have o project for my university and I need to use openrouteservice API.
I registered there and I generate an api-key. At API playground I choose Directions and then I get a basic route between two points with the profile provided. Returned response is in GeoJSON format. This method does not accept any request body or parameters other than profile, start coordinate, and end coordinate.
I need to do this in C#, so this is my class where I want to call this API.
class OpenRouteServiceCall{
private string \_apiKey = "my_key_number";
private HttpClient _client;
private Uri _baseAddress;
public OpenRouteServiceCall()
{
_client = new HttpClient();
_client.DefaultRequestHeaders.Clear();
_client.DefaultRequestHeaders.TryAddWithoutValidation("accept", "application/json, application/geo+json, application/gpx+xml, img/png; charset=utf-8");
}
public async Task<RouteInfo> GetRouteInfo()
{
_baseAddress = new Uri($"https://api.openrouteservice.org/v2/directions/driving-car?api_key={_apiKey}&start=27.589244,%2047.160306&end=27.72833,%2046.641804");
_client.BaseAddress = _baseAddress;
using (var response = await _client.GetAsync("directions"))
{
string responseData = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseData);
var data = JsonConvert.DeserializeObject<RouteInfo>(responseData);
return data;
}
}
}
There is a line Console.WriteLine(responseData); and it shows me " "error": "Authorization field missing" " . And yes, my_key_number is a long string, I have it on my dashboard and the key is still valid.
It's the first time I use an API and I don't know how to proceed in this situation.Please, someone help me.
I need the details from JSON: distance, duration, speed, congestion.

Related

C# Post Variables can't be read on Website - HttpClient PostAsync()

I have a web server on which I'm hosting my own api for one of my projects.
This is the php-code of the api-website:
$user = $_POST['username'];
$password = $_POST['password'];
if(strcmp($user, "username") == 0 && strcmp($password, "password") == 0) {
...
} else {
die("No Permissions");
}
I want to send the two variables username and password with a HttpClient and the postAsync-method to this website and if the right log in data is detected, it returns the data I want.
For this I have the following code in C#:
Task<HttpResponseMessage> response;
var url = "www.url.de"; //not the url I'm actually calling!
var vars = "[{\"username\":\"username\", \"password\":\"password\"}]";
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(url);
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
response = client.PostAsync(url, new StringContent(vars, Encoding.UTF8));
Console.WriteLine(response.Result.Content.ReadAsStringAsync().Result);
if (response.IsCompleted)
{
Console.WriteLine(response.Result.Content.ReadAsStringAsync().Result);
}
}
But the problem is that no matter what I have tried the output from this code is, that i have no permissions. And I have changed the php-code, so that I can see which data is stored in $username and $password, but they are empty and I don't know why. I hope somebody can help me with this.
Your PHP code is expecting the data sent as application/x-www-form-urlencoded, but your C# code is sending it as JSON.
As mentioned in the comment by M. Eriksson, you either need to change your PHP to accept JSON, or change your C# to send as form data.
This answer shows how to use HTTPClient to send data like that.
Here's my modification of your code based on the above code (I did test it):
public static async Task DoSomething()
{
string url = "http://httpbin.org/post"; //not the url I'm actually calling!
Dictionary<string, string> postData = new();
postData["username"] = "username";
postData["password"] = "password";
using HttpClient client = new();
client.DefaultRequestHeaders.Accept.Add(new("application/json"));
HttpRequestMessage request = new(HttpMethod.Post, url);
request.Content = new FormUrlEncodedContent(postData);
HttpResponseMessage response = await client.SendAsync(request);
Console.WriteLine(response.Content.ReadAsStringAsync().Result);
}

Teamcity REST API issue in with POST method

I am trying to create a TeamCity project from .NET Core. I have written the code below but when I am trying to run the code I get an error.
Code:
public void CreateProject(string name, string newProjectId, string parentProjectId)
{
InvokeTeamCityApi(() => _apiClient.CreateProject(new NewProjectDescription
{
Name = name,
Id = newProjectId,
SourceProject = new GetProjectResponse
{
Id = _toolContext.HostingContext.TeamCityProjectTemplate
},
ParentProject = new GetProjectResponse
{
Id = parentProjectId
},
CopyAllAssociatedSettings = true,
}));
}
Error:
403 Forbidden: CSRF Header X-TC-CSRF-Token does not match CSRF session value
Also I did a Google search and I tried adding the header origin but I dont have access to disable the internal teamcity properties to disable CSRF check.
So I am passing the token X-tc-CSRF-Token in the request but it says the value doesn't match. How can I solve this issue?
Note: I am getting this issue only when I am using bearer token and with basic auth it works fine.
I recently had the same issue when upgrading from TeamCity 10 to TeamCity 2022 and eventually managed to find out how to fix it. Importantly, I didn't have to have access the internal TeamCity properties to disable the CSRF check as I figured that it's not a bad thing to have the extra layer of security.
Things that were probably important that I changed:
I generated an access token for the account that I was using to access the REST API so I wouldn't need to put my password in the code. The access token can be associated with more restrictive permissions than your own account.
Using HttpClient, authorisation is achieved by adding a default header (via the DefaultHeaders property) with the name "Authorization" and value "Bearer {apiToken}".
I read the /authenticationTest.html?csrf endpoint to get a CSRF token then add that value as a default header ("X-TC-CSRF-Token"). It's also possible to use the "tc-csrf-token" header in the same way.
Note that because the "Authorization" and "X-TC-CSRF-Token"/"tc-csrf-token" headers are added as default headers, there's no need to do this explicitly on every HTTP (GET, POST ,DELETE, etc.) method.
Here's some sample code which covers all of the above.
public class Sample
{
private readonly string _baseUrl;
private readonly HttpClient _httpClient = new HttpClient();
public Sample(string baseUrl, string accessToken)
{
_baseUrl = baseUrl;
_httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {accessToken}");
var csrfToken = get("/authenticationTest.html?csrf");
_httpClient.DefaultRequestHeaders.Add("X-TC-CSRF-Token", csrfToken);
}
public void CreateProject(string id, string name)
{
post("/app/rest/projects", $"<newProjectDescription id=\"{id}\" name=\"{name}\" />");
}
private string get(string relativeUrl)
{
var getTask = _httpClient.GetAsync(_baseUrl + relativeUrl);
getTask.Wait();
var response = getTask.Result;
response.EnsureSuccessStatusCode();
var readTask = response.Content.ReadAsStreamAsync();
readTask.Wait();
using ( var stream = readTask.Result )
using ( var reader = new StreamReader(stream) )
return reader.ReadToEnd();
}
private void post(string relativeUrl, string data)
{
using ( var content = new StringContent(data, Encoding.UTF8, "application/xml") )
{
var postTask = _httpClient.PostAsync(_baseUrl + relativeUrl, content);
postTask.Wait();
var response = postTask.Result;
response.EnsureSuccessStatusCode();
var readTask = response.Content.ReadAsStreamAsync();
readTask.Wait();
}
}
}
Call it using, e.g.
// Change these according to your situation
var baseUrl = "http://localhost:8111";
var accessToken = "1234567890";
var sample = new Sample(baseUrl, accessToken);
sample.CreateProject("ProjectID", "ProjectName");
Note that this is just a sample to get you on your feet: I've kept the code short by taking various shortcuts in the code (e.g. the HttpClient should really be one static HttpClient for the application: see Guidelines for using HttpClient on learn.microsoft.com).

learning .net core 3.1 - very first attempt at consuming API webservice

I'm brand new to .net core 3.1 - not a lot of oop experience period - I have 20 years software development experience using procedural languages on IBMi. Been working through a tutorial to consume an API that I have created on my IBMi... I'm stuck...
Below is my HomeController... What I'm able to do by running this code thus far...
1.) connects to my IBMi endpoint
2.) it does invoke the correct backend API pgm
3.) backend API pgm does indeed take json string from URI and process it like it should, and produces a json string response.
issues..
1.) ultimately i'd like to pass this json request string in the body and not the URI
2.) while everything is working with passing the json string in the URI, when the json string response is sent back, there is an issue processing that response. My guess is that it is expecting a json object back and not a string.
The error is...
JsonException: The JSON value could not be converted to
System.Collections.Generic.IEnumerable`1[coreiWS.Models.ProductKey].
Path: $ | LineNumber: 0 | BytePositionInLine: 1.
the generated json string response is... (or could also contain a trial key value - nonetheless, both are valid json in string format)...
{
"success": 0,
"resultMessage": "Error RST00001R - Invalid - Product Code Already Granted 2 Trial Keys. Please Email Us At xxxxxxxxxx#gmail.com To
Discuss Your Future Business Requirements Utilizing CoreiRST." }
and the code causing it is...
var responseStream = await response.Content.ReadAsStreamAsync();
productKeys = await JsonSerializer.DeserializeAsync
<IEnumerable<ProductKey>>(responseStream);
I would be extremely grateful for anyone that could help guide me in the right direction with getting this working.
the complete HomeController Code is...
public class HomeController : Controller
{
// jhv - add this...
private readonly IHttpClientFactory _clientFactory;
public IEnumerable<ProductKey> productKeys { get; set; }
public HomeController(IHttpClientFactory clientFactory)
{
_clientFactory = clientFactory;
}
// jhv - add this...
public async Task<IActionResult> Index()
{
//var user = Authenticate().Result;
//if (user == null)
//return View();
var request = new HttpRequestMessage(HttpMethod.Get,
"http://xxxxxxxxxxxxxxxxxxxxxxxxx/{\"env\":\"xxx\",\"command\":\"getTrialKey\",\"payload\":{\"productCode\":\"MFT 102A08R EPCA 00007\"}}");
//request.Headers.Add("Authorization", "Bearer " + user.Token);
request.Headers.Add("Authorization", "Basic xxxxxxxxxxxxxxxxxx");
//request.Headers.Add("text/plain", "{\"env\":\"xxx\",\"command\":\"getTrialKey\",\"payload\":{\"productCode\":\"MFT 102A08R EPCA 00007\"}} \r\n");
var client = _clientFactory.CreateClient();
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("text/plain"));
var response = await client.SendAsync(request);
if(response.IsSuccessStatusCode)
{
var responseStream = await response.Content.ReadAsStreamAsync();
productKeys = await JsonSerializer.DeserializeAsync
<IEnumerable<ProductKey>>(responseStream);
}
else
{
productKeys = new List<ProductKey>();
}
return View(productKeys);
It looks like your JSON is returning a singular object, but you are trying to map it to an IEnumerable<ProductKey>.
That might get you through the first error message.

Is there a way to delete Azure Function from my Function App using C#?

I am trying to delete an Azure function from my Function App through C#.
But while deleting it programmatically, the function is not seen on the User Interface, but when I check it through Advanced tools (Kudu), I can still see my Azure function.
So basically while deleting the Azure function, what I do is, I delete it's function.json, and by doing so the Azure function isn't visible in Functions App list (see image below)
But when I go to Advanced Kudu to check whether it has been deleted, I can still see it, but without the function.json file. I had done this before (around 6 months back) and back then it was working properly. I don't know if I am doing it wrong or has anything changed.
Any help with the code would be appreciated.
Thanks
Edit:
The details that I have with me is the Function App's username, password, url, name (https://my-function-app.scm.azurewebsites.net/api/vfs/site/wwwroot), and azure function's name.
A little sample code of what I did which worked 6 months back
private WebClient _webClient = new WebClient
{
Headers = { ["ContentType"] = "application/json" },
Credentials = new NetworkCredential(username, password),
BaseAddress = functionsSiteRoot,
};
var functionJson =
JsonConvert.DeserializeObject<FunctionSettings>(_webClient.DownloadString("MyFunctionName/function.json"));
_webClient.Headers["If-Match"] = "*";
_webClient.UploadString("MyFunctionName/function.json", "DELETE", JsonConvert.SerializeObject(functionJson));
You could use REST API to perform this operation.
https://management.azure.com/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Web/sites/{name}/functions/{functionName}?api-version=2016-08-01
Method: DELETE
Code Snippet:
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Delete, string.Format("https://management.azure.com/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Web/sites/{name}/functions/{functionName}?api-version=2016-08-01", "Pass All Param In {}")));
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", results.access_token);
HttpResponseMessage response = await _client.SendAsync(request);
if (response.IsSuccessStatusCode)
{
dynamic objApiResponse = JsonConvert.DeserializeObject<dynamic>(await response.Content.ReadAsStringAsync());
}
else
{
return req.CreateResponse(HttpStatusCode.OK, "Sorry Invalid Request");
}
For details please have a look on official docs
Note: For token request your resource/Scope should be https://management.azure.com. Pass your token while send request.
Update:
You can request for token using client_credentials authentication flow. Try below format:
Azure Portal Credentials For App Id and Tenant Id:
Application Secret from Portal:
Token Endpoint Or URL:
https://login.microsoftonline.com/YourTenantName.onmicrosoft.com/oauth2/token
Request Param:
grant_type:client_credentials
client_id:b603c7be_Your_App_ID_e6921e61f925
client_secret:Vxf1Sl_Your_App_Secret_2XDSeZ8wL/Yp8ns4sc=
resource:https://graph.microsoft.com
PostMan Sample:
Token On Response:
Code Snippet For Token:
//Token Request End Point
string tokenUrl = $"https://login.microsoftonline.com/YourTenant/oauth2/token";
var tokenRequest = new HttpRequestMessage(HttpMethod.Post, tokenUrl);
//I am Using client_credentials as It is mostly recomended
tokenRequest.Content = new FormUrlEncodedContent(new Dictionary<string, string>
{
["grant_type"] = "client_credentials",
["client_id"] = "20e08e95-_Your_App_ID_e9c711b0d19e",
["client_secret"] = "+trl[ZFl7l_Your_App_Secret__ghon9",
["resource"] = "https://management.azure.com/"
});
dynamic json;
AccessTokenClass results = new AccessTokenClass();
HttpClient client = new HttpClient();
var tokenResponse = await client.SendAsync(tokenRequest);
json = await tokenResponse.Content.ReadAsStringAsync();
results = JsonConvert.DeserializeObject<AccessTokenClass>(json);
//New Block For Accessing Data from API
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Delete, string.Format("https://management.azure.com/subscriptions/YOurSubscription/resourceGroups/YourResourceGroup/providers/Microsoft.Web/sites/DeleteTestFuncAppName/functions/DeleteFunctionNameThatYouWantToDelete?api-version=2016-08-01"));
//Passing Token For this Request
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", results.access_token);
HttpResponseMessage response = await client.SendAsync(request);
//Read Server Response
dynamic objServerResponse = JsonConvert.DeserializeObject<dynamic>(await response.Content.ReadAsStringAsync());
Class I Have Used:
public class AccessTokenClass
{
public string token_type { get; set; }
public string expires_in { get; set; }
public string resource { get; set; }
public string scope { get; set; }
public string access_token { get; set; }
public string refresh_token { get; set; }
}
Point To Remember:
If you got this error
InvalidAuthenticationToken: The received access token is not valid: at
least one of the claims 'puid' or 'altsecid' or 'oid' should be
present. If you are accessing as application please make sure service
principal is properly created in the tenant
You have to assign role to your application like below:

Call and consume Web API in winform using C#.net

I am beginner and creating winform application. In which i have to use API for Simple CRUD operation. My client had shared API with me and asked to send data in form of JSON.
API : http://blabla.com/blabla/api/login-valida
KEY : "HelloWorld"
Value : { "email": "user#gmail.com","password": "123456","time": "2015-09-22 10:15:20"}
Response : Login_id
How can i convert data to JSON, call API using POST method and get response?
EDIT
Somewhere on stackoverflow i found this solution
public static void POST(string url, string jsonContent)
{
url="blabla.com/api/blala" + url;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(baseURL);
request.Method = "POST";
System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();
Byte[] byteArray = encoding.GetBytes(jsonContent);
request.ContentLength = byteArray.Length;
request.ContentType = #"application/json";
using (Stream dataStream = request.GetRequestStream())
{
dataStream.Write(byteArray, 0, byteArray.Length);
}
long length = 0;
try
{
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
length = response.ContentLength;
}
}
catch
{
throw;
}
}
//on my login button click
private void btnLogin_Click(object sender, EventArgs e)
{
CallAPI.POST("login-validate", "{ \"email\":" + txtUserName.Text + " ,\"password\":" + txtPassword.Text + ",\"time\": " + DateTime.Now.ToString("yyyy-MM-dd h:mm tt") + "}");
}
I got exception that says "The remote server returned an error: (404) Not Found."
You can take a look at the following docs tutorial:
Call a Web API From a .NET Client
But as an answer, here I will share a quick and short a step by step guide about how to call and consume web API in Windows forms:
Install Package - Install the Microsoft.AspNet.WebApi.Client NuGet package (Web API Client Libraries).
Open Tools menu → NuGet Package Manager → Package Manager Console → In the Package Manager Console window, type the following command:
Install-Package Microsoft.AspNet.WebApi.Client
You can install package by right click on project and choosing Manage NuGet Packages as well.
Set up HttpClient - Create an instance of HttpClient and set up its BaseAddress and DefaultRequestHeaders. For example:
// In the class
static HttpClient client = new HttpClient();
// Put the following code where you want to initialize the class
// It can be the static constructor or a one-time initializer
client.BaseAddress = new Uri("http://localhost:4354/api/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
Send Request - To send the requests, you can use the following methods of the HttpClient:
GET: GetAsync, GetStringAsync, GetByteArrayAsync, GetStreamAsync
POST: PostAsync, PostAsJsonAsync, PostAsXmlAsync
PUT: PutAsync, PutAsJsonAsync, PutAsXmlAsync
DELETE: DeleteAsync
Another HTTP method: Send
Note: To set the URL of the request for the methods, keep in mind, since you have specified the base URL when you defined the client, then here for these methods, just pass path, route values and query strings, for example:
// Assuming http://localhost:4354/api/ as BaseAddress
var response = await client.GetAsync("products");
or
// Assuming http://localhost:4354/api/ as BaseAddress
var product = new Product() { Name = "P1", Price = 100, Category = "C1" };
var response = await client.PostAsJsonAsync("products", product);
Get the Response
To get the response, if you have used methods like GetStringAsync, then you have the response as string and it's enough to parse the response. If the response is a Json content which you know, you can easily use JsonConvert class of Newtonsoft.Json package to parse it. For example:
// Assuming http://localhost:4354/api/ as BaseAddress
var response = await client.GetStringAsync("product");
var data = JsonConvert.DeserializeObject<List<Product>>(response);
this.productBindingSource.DataSource = data;
If you have used methods like GetAsync or PostAsJsonAsync and you have an HttpResponseMessage then you can use ReadAsAsync, ReadAsByteArrayAsync, ReadAsStreamAsync, `ReadAsStringAsync, for example:
// Assuming http://localhost:4354/api/ as BaseAddress
var response = await client.GetAsync("products");
var data = await response.Content.ReadAsAsync<IEnumerable<Product>>();
this.productBindingSource.DataSource = data;
Performance Tip
HttpClient is a type that is meant to be created once and then shared. So don't try to put it in a using block every time that you want to use it. Instead, create an instance of the class and share it through a static member. To read more about this, take a look at Improper Instantiation antipattern
Design Tip
Try to avoid mixing the Web API related code with your application logic. For example let's say you have a product Web API service. Then to use it, first define an IProductServieClient interface, then as an implementation put all the WEB API logic inside the ProductWebAPIClientService which you implement to contain codes to interact with WEB API. Your application should rely on IProductServieClient. (SOLID Principles, Dependency Inversion).
Just use the following library.
https://www.nuget.org/packages/RestSharp
GitHub Project: https://github.com/restsharp/RestSharp
Sample Code::
public Customer GetCustomerDetailsByCustomerId(int id)
{
var client = new RestClient("http://localhost:3000/Api/GetCustomerDetailsByCustomerId/" + id);
var request = new RestRequest(Method.GET);
request.AddHeader("X-Token-Key", "dsds-sdsdsds-swrwerfd-dfdfd");
IRestResponse response = client.Execute(request);
var content = response.Content; // raw content as string
dynamic json = JsonConvert.DeserializeObject(content);
JObject customerObjJson = json.CustomerObj;
var customerObj = customerObjJson.ToObject<Customer>();
return customerObj;
}
Use Json.Net to convert data into JSON
Use WebClient to POST data
Use This code:
var client = new HttpClient();
client.BaseAddress = new Uri("http://www.mywebsite.com");
var request = new HttpRequestMessage(HttpMethod.Post, "/path/to/post/to");
var keyValues = new List<KeyValuePair<string, string>>();
keyValues.Add(new KeyValuePair<string, string>("site", "http://www.google.com"));
keyValues.Add(new KeyValuePair<string, string>("content", "This is some content"));
request.Content = new FormUrlEncodedContent(keyValues);
var response = await client.SendAsync(request);
Here is another example using an online REST service (https://northwind.vercel.app) which allows interaction with Northwind API.
This example uses HttpClient and JsonConvert to get or post data. Here is a very quick example:
Install Newtonsoft.Json nuget package. And add the following using statements to your form:
using System.Net.Http;
using Newtonsoft.Json
Define an instance of the HttpClient, at class level:
private static HttpClient client = new HttpClient();
To send a GET request, for example getting list of all data:
var url = "https://northwind.vercel.app/api/categories";
var response = await client.GetAsync(url);
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
var content = await response.Content.ReadAsStringAsync();
var categories = JsonConvert.DeserializeObject<List<Category>>(content);
dataGridView1.DataSource = categories;
}
You can also use other overloads of Get, like GetStringAsync, GetStreamAsync, and etc. But GetAsync is a more generic method allowing you to get the status code as well.
To send a POST request, for example posting a new data:
var url = "https://northwind.vercel.app/api/categories";
var data = new Category() { Name = "Lorem", Description = "Ipsum" };
var jsonData = Newtonsoft.Json.JsonConvert.SerializeObject(data);
var requestContent = new StringContent(jsonData, Encoding.Unicode, "application/json");
var response = await client.PostAsync(url, requestContent);
if (response.StatusCode == System.Net.HttpStatusCode.Created)
{
var content = await response.Content.ReadAsStringAsync();
var createdCategory = JsonConvert.DeserializeObject<Category>(content);
MessageBox.Show(createdCategory.Id.ToString())
}
To learn more and see some best practices or see an example without JsonConvert, see my other post.

Categories