Using DefaultRequestHeaders sends requests twice? - c#

I have a WebAPI that sends BASIC authorization information as following.
var client = new HttlpClient();
client.BaseAddress = new Uri(GlobalConstants.LdapUri);
var contentType = new MediaTypeWithQualityHeaderValue("application/json");
client.DefaultRequestHeaders.Accept.Add(contentType);
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes(string.Format("{0}:{1}", userName, password))));
Task<HttpResponseMessage> results = client.GetAsync(GlobalConstants.FortressAPIUriDev);
var response = await results;
I've built this API using MVC Core 1.x and the receiving API is built using MVC5.
The problem is that this GetAsync sends two requests at the same time, and I have no clue how to resolve this. I've done some Googling myself to see if I can find a fix for this but so far no luck. Did anyone experience this problem and know how to resolve it?
Thank you very much in advance.

Long story short, found a solution as follows:
using (var client = new HttpClient())
{
var requestMessage = new HttpRequestMessage(HttpMethod.Get, GlobalConstants.LdapUri + GlobalConstants.FortressAPIUriDev);
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes(string.Format("{0}:{1}", userName, password))));
var response = await client.SendAsync(requestMessage);
}
After replacing with this code, it is sending one request at a time.
Found a hint at :
Adding headers when using httpClient.GetAsync

Related

C# API Beginner

I have the following code as a start to create a API Call to https://jsonplaceholder.typicode.com/posts/. I want to practice making the call, receive a JSON response and then..do stuff.
How can I finish this off to get a response so I can iterate through the response array.
using (HttpClient client = new HttpClient())
{
client.BaseAddress = new Uri(URL);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get,"");
request.Content = new StringContent(URL, Encoding.UTF8,"application/json");
Wiring this in VS Code so will need to install packages if needed.
Thank you!
You are almost there. Try (if you want a simple synchronous send):
HttpClient client = new HttpClient();
string responseString;
using (HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, new Uri("<insert your URL>"))) {
HttpResponseMessage response = client.SendAsync(request).Result;
// Get the response content as a string
responseString = response.Content.ReadAsStringAsync().Result;
}
Note that it's good practice to initialize one instance of HttpClient and reuse it to send multiple requests (rather than initialize one every time you need to send something).
Any headers, URLs and such specific to a message should be set in the HttpRequestMessage class (which should be disposed of with the "using ..." term.

C# to pause, turn on ssas server, backup cube.... how to?

I'm building some function apps in C# (via REST API) to make refreshes of tabular cube located on an azure ssas server. So far, no problem. However, I can't find a way to pause/start the ssas server (I saw some doc in powershell but I'd like to stay in C# so as not to mix languages)
Has anyone ever created anything like this?
I tried to make a POST suspend but no solution for now.
See the ResumeAzureAS() method here:
protected async Task<bool> ResumeAzureAS()
{
HttpClient client = new HttpClient();
var apiURI = new Uri(string.Format("https://management.azure.com/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.AnalysisServices/servers/{2}/resume?api-version=2016-05-16", subscriptionID, resourcegroup, server));
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
HttpResponseMessage response = await client.PostAsync(apiURI.ToString(), null);
response.EnsureSuccessStatusCode();
return true;
}
The rest of the API calls (such as suspend) are documented here.
private async Task<string> AASAcquireToken()
{
// Get auth token and add the access token to the authorization header of the request.
string authority = "https://login.windows.net/" + tenant + "/oauth/authorize";
AuthenticationContext ac = new AuthenticationContext(authority);
ClientCredential cred = new ClientCredential(clientID, keyID);
AuthenticationResult ar = await ac.AcquireTokenAsync(audience, cred);
return ar.AccessToken;
}
With audience set as "https://management.azure.com"
and for the "pause" itself :
I use as servername the complete name mention in the portal azure as "asazure://northeurope.asazure.windows...."
For the version of the api , well I don't know where to find it so I use one I found on the net.
var apiURI = new Uri(string.Format("https://management.azure.com/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.AnalysisServices/servers/{2}/suspend?api-version=2016-05-16", subscription, ressourceID, servername));
audience = "https://management.azure.com";
myClient.BaseAddress = new Uri(location);
myClient.DefaultRequestHeaders.Accept.Clear();
myClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
myClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", await AASAcquireToken());
HttpResponseMessage response = await myClient.PostAsync(apiURI.ToString(), null);
var output = await response.Content.ReadAsStringAsync();
response.EnsureSuccessStatusCode();
The right audience was :
audience = "https://management.core.windows.net/";

Performing a put or patch request with token

I've got a chunk of code:
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes(String.Format("{0}:{1}", "Username", "password"))));
var method = new HttpMethod("PATCH");
var reqmsg = new HttpRequestMessage(method, uri)
{
Content = new StringContent(request, Encoding.UTF8, "application/json")
};
HttpResponseMessage response = await client.SendAsync(reqmsg);
This works fine using Basic authentication. I want to use a token though, and if I change the Authorization to use a webtoken:
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Token", WebToken);
I now get a 403 Forbidden error. If I'm doing a Post or a Get, the token works, but not for Patch or Put. I'm guessing the token is somehow being stripped off. is there a way around this?
You're getting a 403 error because the encoding is incorrect.
-facepalm-
You're using UTF8 while the default is ANCI... Doesn't make sense.

Adding authentication header to HttpClient

I'm trying to access an API, but all the documentation is in PHP and I'm not very familiar with PHP. I am having trouble authenticating to the API. The documentation is here.
Here is what I have so far
var webAddress = "https://xboxapi.com/v2/latest-xbox360-games";
var httpResponse = (new HttpClient().GetAsync(webAddress)).Result;
httpResponse.EnsureSuccessStatusCode();
var jsonResponse = httpResponse.Content.ReadAsStringAsync().Result;
I'm just not sure how to add the authentication header that they are using in PHP.
Any help would be appreciated.
To add a custom header (in this case X-AUTH), you need to send a custom HttpRequestMessage. For example:
var webAddress = "https://xboxapi.com/v2/latest-xbox360-games";
HttpClient client = new HttpClient();
HttpRequestMessage msg = new HttpRequestMessage(HttpMethod.Get, webAddress);
msg.Headers.Add('X-AUTH', 'your-auth-key-here');
HttpResponseMessage response = await client.SendAsync(msg);

HttpClient authentication header not getting sent

I'm trying to use an HttpClient for a third-party service that requires basic HTTP authentication. I am using the AuthenticationHeaderValue. Here is what I've come up with so far:
HttpRequestMessage<RequestType> request =
new HttpRequestMessage<RequestType>(
new RequestType("third-party-vendor-action"),
MediaTypeHeaderValue.Parse("application/xml"));
request.Headers.Authorization = new AuthenticationHeaderValue(
"Basic", Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(
string.Format("{0}:{1}", "username", "password"))));
var task = client.PostAsync(Uri, request.Content);
ResponseType response = task.ContinueWith(
t =>
{
return t.Result.Content.ReadAsAsync<ResponseType>();
}).Unwrap().Result;
It looks like the POST action works fine, but I don't get back the data I expect. Through some trial and error, and ultimately using Fiddler to sniff the raw traffic, I discovered the authorization header isn't being sent.
I've seen this, but I think I've got the authentication scheme specified as a part of the AuthenticationHeaderValue constructor.
Is there something I've missed?
Your code looks like it should work - I remember running into a similar problem setting the Authorization headers and solved by doing a Headers.Add() instead of setting it:
request.Headers.Add("Authorization", "Basic " + Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(string.Format("{0}:{1}", "username", "password"))));
UPDATE:
It looks like when you do a request.Content, not all headers are being reflected in the content object. You can see this by inspecting request.Headers vs request.Content.Headers. One thing you might want to try is to use SendAsync instead of PostAsync. For example:
HttpRequestMessage<RequestType> request =
new HttpRequestMessage<RequestType>(
new RequestType("third-party-vendor-action"),
MediaTypeHeaderValue.Parse("application/xml"));
request.Headers.Authorization =
new AuthenticationHeaderValue(
"Basic",
Convert.ToBase64String(
System.Text.ASCIIEncoding.ASCII.GetBytes(
string.Format("{0}:{1}", "username", "password"))));
request.Method = HttpMethod.Post;
request.RequestUri = Uri;
var task = client.SendAsync(request);
ResponseType response = task.ContinueWith(
t =>
{ return t.Result.Content.ReadAsAsync<ResponseType>(); })
.Unwrap().Result;
This would also work and you wouldn't have to deal with the base64 string conversions:
var handler = new HttpClientHandler();
handler.Credentials = new System.Net.NetworkCredential("username", "password");
var client = new HttpClient(handler);
...
Try setting the header on the client:
DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes(String.Format("{0}:{1}", userName, password))));
This works for me.
Also, consider that Redirect-Handler will clear the Authorization header if your request gets redirected.
So if you call an HTTP endpoint and it redirected to the HTTPS one, you will lose your authorization header.
request.Headers.Authorization = null;
Framework: .NET v6.0
Actually your problem is with PostAsync- you should use SendAsync. In your code - client.PostAsync(Uri, request.Content); sends only the content the request message headers are not included.
The proper way is:
HttpRequestMessage message = new HttpRequestMessage(HttpMethod.Post, url)
{
Content = content
};
message.Headers.Authorization = new AuthenticationHeaderValue("Basic", credentials);
httpClient.SendAsync(message);

Categories