I'm new to Azure API management Rest Service. I created a new API Management, with a sharedaccesstoken.
using (HttpClient httpClient = new HttpClient())
{
var request = new HttpRequestMessage(HttpMethod.Post, requestUrl);
request.Headers.Authorization =
new AuthenticationHeaderValue("SharedAccessSignature", sharedAccessSignature);
request.Content = new StringContent("{\"accountEnabled\": true,\"creationType\": \"LocalAccount\",\"displayName\": \"Alex Wu\",\"passwordProfile\": {\"password\": \"Test1234\",\"forceChangePasswordNextLogin\": false},\"signInNames\": [{\"type\": \"userName\",\"value\": \"AlexW\"},{\"type\": \"emailAddress\",\"value\": \"AlexW#example.com\"}]}");
HttpResponseMessage response = await httpClient.SendAsync(request);
response.EnsureSuccessStatusCode();
responseBody = await response.Content.ReadAsStringAsync();
}
When i execute the code above i get a error:
{StatusCode: 405, ReasonPhrase: 'Method Not Allowed', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:{ Date: Wed, 30 Mar 2016 19:38:15 GMT Content-Length: 73 Allow: GET Content-Type: application/json; charset=utf-8}}
Can someone help me moving forward so I will be able to create new users via the REST service.
I just read up on the API Reference specified in https://learn.microsoft.com/en-us/rest/api/apimanagement/user/createorupdate.
For starters, you should use HttpMethod.Put instead of Post. The request path should be base url + /users/{unique uid}. Also, from what I can tell, the attributes you are trying to pass are not available for this transaction.
If it's something else you're actually trying to accomplish then creating an Azure API Management User Entity, please advice and I'll try to guide you further.
Your answer helped me indeed. Below the implementation which made me accomplish my task.
string requestUrl = string.Format("{0}/users/{1}?api-version={2}", baseUrl, userGuid, apiVersion);
string responseBody = null;
try
{
using (HttpClient httpClient = new HttpClient())
{
var request = new HttpRequestMessage(HttpMethod.Put, requestUrl);
request.Headers.Authorization =
new AuthenticationHeaderValue("SharedAccessSignature", sharedAccessSignature);
request.Content = new StringContent("{\"firstName\": \"MyFirstName\",\"lastName\": \"MyLastName\",\"email\": \"example#mail\",\"password\": \"Password;\",\"state\": \"active\"}", Encoding.UTF8,"application/json");
HttpResponseMessage response = await httpClient.SendAsync(request);`enter code here`
response.EnsureSuccessStatusCode();
responseBody = await response.Content.ReadAsStringAsync();
}
}
Related
I am new to the C# world, and can't for the life of me figure out how to get around this error. I am trying to make a simple get request using a platform API key. I have built out the API connection in Google App Script on the same laptop, and it works fine, but when trying to build out the same API in C#, it is returning:
{StatusCode: 403, ReasonPhrase: 'Forbidden', Version: 1.1, Content: System.Net.Http.HttpConnectionResponseContent, Headers:
{
Date: Sun, 13 Mar 2022 02:41:29 GMT
Transfer-Encoding: chunked
Connection: close
CF-Chl-Bypass: 1
Permissions-Policy: accelerometer=(),autoplay=(),camera=(),clipboard-read=(),clipboard-write=(),fullscreen=(),geolocation=(),gyroscope=(),hid=(),interest-cohort=(),magnetometer=(),microphone=(),payment=(),publickey-credentials-get=(),screen-wake-lock=(),serial=(),sync-xhr=(),usb=()
Cache-Control: private, max-age=0, no-store, no-cache, must-revalidate, post-check=0, pre-check=0
X-Frame-Options: SAMEORIGIN
Expect-CT: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
Strict-Transport-Security: max-age=2592000
Server: cloudflare
CF-RAY: 6eb1692f8bd776c3-LHR
Content-Type: text/html; charset=utf-8
Expires: Thu, 01 Jan 1970 00:00:01 GMT
}}
The API documentation says:
"To authenticate against the API, include your API key in the 'Authorization' header, prefixed with 'Key ', in every request. Example: 'Authorization: Key yourapikey'"
And so, I have tried adding this to
a) the HttpClient via HttpClient.DefaultRequestHeaders.Authorization
b) the HttpClient via HttpClient.DefaultHeaders.Add
c) the HttpRequestMessage via HttpRequestMessage.Headers.Add
In each instance, the request URI looks good, as well as the headers, but still returning 403.
My current structure is:
// services
builder.Services.AddHttpClient("myplatform", c =>
{
c.BaseAddress = new Uri("https://seller-api.myplatform.com/v2/");
c.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
});
// controller
// constructor uses IHttpClientFactory
this._httpClient = clientFactory.CreateClient("myplatform");
// service
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Key", platformKey);
string endPoint = "offers" + CreateQueryString(pageNumber, pageSize);
// example endPoint: offers?page_number=1&page_size=100
var requestMsg = new HttpRequestMessage()
{
Method = HttpMethod.Get,
RequestUri = new Uri(httpClient.BaseAddress + endPoint)
};
try
{
var result = await httpClient.SendAsync(requestMsg);
}
catch (Exception ex)
{
}
Again, the content of the call works when calling through GoogleAppScript. What am I doing wrong in C#, and how can I correct this?
Not sure if this is all the information needed - let me know otherwise! Important to note, the target framework is .NET 6.0.
EDIT
As suggested by a comment around duplicate clients, I have removed the client factory. I am now creating a new HttpClient in the controller constructor, and passing this client to my service to do the GET request.
this._httpClient = new HttpClient();
Again, the client and the request message look well formed at time of request but still returning 403 error. Is there an issue with my VS22 client, or web client etc.?
Also, the call I am making successfully via Google AppScript is using UrlFetchApp. Not sure what is the issue here with the C# side..
EDIT2
Adding current GAS code for reference:
var url = 'https://seller-api.platform.com/v2';
var end_point = '/offers?';
var header = {
'Authorization': api_key
}
var params = {
'method': 'GET',
'headers': header
}
// call API
var page_query = 'page_number=' + page + '&page_size=' + maxItemsPerPage;
var full_url = url + end_point + page_query;
var response = UrlFetchApp.fetch(full_url, params);
The HTTP 403 Forbidden response status code indicates that the server understands the request but refuses to authorize it.
There are two ways add request headers when using HttpClient:
Add headers for all requests using HttpClient.DefaultRequestHeaders.
HttpClient = new HttpClient();
HttpClient.DefaultRequestHeaders.Add("Key", platformKey);
var response = await HttpClient.GetAsync(GetRandomNumberUrl);
response.EnsureSuccessStatusCode();
await response.Content.ReadAsStringAsync();
Add headers per request using HttpRequestMessage.Headers.
HttpClient = new HttpClient();
using (var request = new HttpRequestMessage(HttpMethod.Get, randomNumberUrl))
{
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", platformKey);
var response = await HttpClient.SendAsync(request);
response.EnsureSuccessStatusCode();
await response.Content.ReadAsStringAsync();
}
Your problem is here in this line:
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Key", platformKey);
your _httpClient and Authorization httpClient is not same instance.
Try this way:
HttpClient HttpClient = new HttpClient();
string url = "https://seller-api.platform.com/v2";
string end_point = "/offers?";
string api_key = "key here";
string page_query = "page_number=" + 10 + "&page_size=" + 20;
string full_url = url + end_point + page_query;
using (var request = new HttpRequestMessage(HttpMethod.Get, url))
{
request.Headers.Add("Authorization", api_key);
var response = await HttpClient.SendAsync(request);
response.EnsureSuccessStatusCode();
var m = await response.Content.ReadAsStringAsync();
}
Solution 2:
Try calling it like a browser :
HttpClient httpClient = new HttpClient();
string url = "https://gatewayt.whatever.com/chkt/request/request.php";
string end_point = "/offers?";
string api_key = "key here";
string page_query = "page_number=" + 10 + "&page_size=" + 20;
string full_url = url + end_point + page_query;
httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Accept", "text/html,application/xhtml+xml,application/xml");
httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Accept-Encoding", "gzip, deflate");
httpClient.DefaultRequestHeaders.TryAddWithoutValidation("User-Agent", "Mozilla/5.0 (Windows NT 6.2; WOW64; rv:19.0) Gecko/20100101 Firefox/19.0");
httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Accept-Charset", "ISO-8859-1");
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Key", api_key);
var response = await httpClient.GetAsync(url);
response.EnsureSuccessStatusCode();
await response.Content.ReadAsStringAsync();
source: Request like browser Link1 Link2 Link3
I have a problem about 502 gateway error in my production server.
I try to develop an application which calls azure rest endpoints. I get response with Postman by sending the endpoint which has following documentation:
https://learn.microsoft.com/en-us/rest/api/azure/devops/wit/classification-nodes/get?view=azure-devops-rest-6.0
While Postman or Invoke-RestMethod work well with azure endpoint, but API, developed by me, based on HttpClient/RestSharp give an 502 Bad gateway error. HttpClient code part can be found below:
var personalaccesstoken = "<my-token>";
using (HttpClient client = new HttpClient())
{
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic",
Convert.ToBase64String(ASCIIEncoding.ASCII.GetBytes(string.Format("{0}:{1}", "<my-email-address>", personalaccesstoken))));
HttpRequestMessage requestMessage = new HttpRequestMessage();
requestMessage.Method = HttpMethod.Get;
requestMessage.RequestUri = new Uri("<my-azure-server-address>/_apis/wit/classificationNodes/Areas?$depth=100");
using (HttpResponseMessage response = client.SendAsync(requestMessage).Result)
{
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseBody);
return responseBody;
}
}
How can I solve the problem or which tool can I use to find the exact problem?
Thank you in advance:
I have GraphQL running on localhost (http://localhost:23061/graphql) and I'm trying to replicate the query I do in the UI directly but within C#. I have verified that the JSON package is correct on postman beforehand but whenever such package is attempted in C# it will just return a 500 error, I tried quite a few variations of this package (swapping " with ' as an example) but unfortunately all the same.
So the query I used on postman is {"query":"{goldBalance(address: "0xa49d64c31A2594e8Fb452238C9a03beFD1119963")}"} this returns just fine in postman.
When moving this to C# however;
static async System.Threading.Tasks.Task Main(string[] args)
{
var httpClient = new HttpClient();
var url = "http://localhost:23061/graphql";
var data = "{ \"query\":\"{goldBalance(address: \"0xa49d64c31A2594e8Fb452238C9a03beFD1119963\")}\"}";
var content = new StringContent(data.ToString(), Encoding.UTF8, "application/json");
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
var result = httpClient.PostAsync(url, content).Result;
Console.WriteLine(result);
}
When this is ran, it will always return;
StatusCode: 500, ReasonPhrase: 'Internal Server Error', Version: 1.1, Content: System.Net.Http.HttpConnectionResponseContent, Headers:
{
Date: Tue, 30 Mar 2021 20:18:36 GMT
Server: Kestrel
Content-Length: 0
}
I thought initially that this could be a HTTPClient issue but WebRequest, so it is clearly an issue on my send somewhere.
Here is what I get using a similar request with Postman:
var client = new RestClient("http://localhost:23061/graphql");
client.Timeout = -1;
var request = new RestRequest(Method.POST);
request.AddHeader("Authorization", "Basic Og==");
request.AddHeader("Content-Type", "text/plain");
request.AddParameter("text/plain", "{\"query\":\"{goldBalance(address: \"0xa49d64c31A2594e8Fb452238C9a03beFD1119963\")}\"}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
Console.WriteLine(response.Content);
Try using this instead of the HttpClient.
Thanks to Hanlet, Postman has a code snippet section that literally has the solution. Appreciated.
I have also now figured out what the issue was, I didn't double escape around the address. Thanks.
I am using oAuth to authenticate my app. I managed to get a code, access_token and refresh_token. So the next step would be trying to get info about the current user.
public async void GetCurrentUser()
{
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", AccessToken);
var response = await client.GetAsync("https://oauth.reddit.com/api/v1/me");
if (response.IsSuccessStatusCode)
{
var json = await response.Content.ReadAsStringAsync();
var obj = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(json);
}
}
}
This is the method I am using to do that. However the response is always an 403 (Forbidden) error code. Any idea what could be wrong? The access_token is what I got when I made a request to https://oauth.reddit.com/api/v1/access_token
I think the token is correct because when I create the same request with Fiddler it works.
ANSWER:
Fixed it by adding a custom user-agent
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, _endpointUri + "me");
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", AccessToken);
request.Headers.Add("User-Agent", Uri.EscapeDataString("android:com.arnvanhoutte.redder:v1.2.3 (by /u/nerdiator)"));
var response = await client.SendAsync(request);
I'm using the following code to post a message to the server.
String credentials="email=me#here.com&pass=abc123";
using (HttpClient client = new HttpClient())
{
HttpResponseMessage message = await client.PostAsync(
url, new StringContent(credentials));
result = await message.Content.ReadAsStringAsync();
}
However, the server responds with an error message saying that the email or pass isn't there.
{\"status\":\"error\",\"message\":\"Email or pass is missing\"}
Now, I can see it's lying but what can be done about it? Am I not providing the credentials as post data (the equivalent of "params" that can be seen if invoked from URL line in FF, as the image below shows?
I also noticed that when I access the RequestMessage like below, I get the URL but no credentials having been sent. What stupid thing am I missing?!
result = message.RequestMessage.ToString();
This result gives me the following string.
Method: POST, RequestUri: 'https://server.com/gettoken', Version: 1.1, Content: System.Net.Http.StringContent, Headers:\u000d\u000a{\u000d\u000a Content-Type: text/plain; charset=utf-8\u000d\u000a Content-Length: 56\u000d\u000a}
You should use the FormUrlEncodedContent to pass your POST data, instead of a StringContent object.
var credentials = new FormUrlEncodedContent(new[] {
new KeyValuePair<string, string>("email", "me#here.com"),
new KeyValuePair<string, string>("pass", "abc123")
});
using (HttpClient client = new HttpClient())
{
HttpResponseMessage message = await client.PostAsync(
url, credentials);
result = await message.Content.ReadAsStringAsync();
}