HttpClient access url with '#' (at symbol) - c#

I'm integrating a service that returns a key when I a GET request to a URL that is in the following format:
https://username:password#service.com/refresh.key
When I access the URL in my browser, it returns the new key as expected, by when I do a GET request using HttpClient I get a 401.
HttpClient _client = new HttpClient();
var response = await _client.GetAsync(#"https://username:password#service.com/refresh.key"); // Returns a 401
I think it has something to do with the '#' in the URL, but I'm not sure how to fix it, I tried replacing it with '%40', but when I do that I get a UriFormatException.
Does anyone know how to do this?

You should modify Authorization header of HttpClient, can you try the code below;
HttpClient _client = new HttpClient();
byte[] usernamePasswordBytes = Encoding.ASCII.GetBytes("user:pass");
_client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", Convert.ToBase64String(usernamePasswordBytes));
var response = await _client.GetAsync(#"https://service.com/refresh.key");
PS: Such username:pass#domain.com requests are BasicAuthentication request so in fact you try to make basic authentication request.
Hope this works for you

You don't need to provide credentials in url. Instead you can do:
using (var handler = new HttpClientHandler {Credentials = new NetworkCredential("username", "password")}) {
using (HttpClient _client = new HttpClient(handler)) {
var response = await _client.GetAsync(#"https://service.com/refresh.key");
}
}

Related

404 when accessing Design Automation API v3 through HttpClient

Running calls to the Design Automation API in Postman works just fine but when I try to make the same calls in C# using HttpClient they fail with a 404 that seems to actually hide an authentication error:
{
"developerMessage":"The requested resource does not exist.",
"userMessage":"",
"errorCode":"ERR-002",
"more info":"http://developer.api.autodesk.com/documentation/v1/errors/err-002"
}
That link leads to an authentication error:
<Error>
<Code>AccessDenied</Code>
<Message>Access Denied</Message>
<RequestId>1F52E60A45AEF429</RequestId>
<HostId>
[ Some base64 ]
</HostId>
</Error>
I'm following examples for how to use HttpClient, but I may be missing something. I successfully get the access token, run
var client = new HttpClient
{
BaseAddress = new Uri("https://developer.api.autodesk.com/da/us-east")
};
client.DefaultRequestHeaders.Authorization =
new System.Net.Http.Headers.AuthenticationHeaderValue(TokenType, AccessToken);
then
var result = await client.GetAsync("/v3/forgeapps/me");
and the above json is the result's content. I use the same access token in Postman and it works.
I would wrap up the endpoint, headers, and httpmethod in the HttpRequestMessage. Then send it and assign it to HttpResponseMessage.
var client = new HttpClient
{
BaseAddress = new Uri("https://developer.api.autodesk.com/da/us-east/")
};
//throw the endpoint and HttpMethod here. Could also be HttpMethod.Post/Put/Delete (for your future reference)
var request = new HttpRequestMessage(HttpMethod.Get, "v3/forgeapps/me");
//also maybe try throwing the headers in with the request instead of the client
request.Headers.Add(TokenType, AccessToken);
// send the request, assign to response
HttpResponseMessage response = await client.SendAsync(request);
//then, we can grab the data through the Content
string result = await response.Content.ReadAsStringAsync();

Httpclient Cookie Issue

Issue: I am trying to use httpclient for fetching data from a site.Now the site requires you to first visit a link then only you can post data to the next link.
Link1 is a simple get request
Link2 is a post request
Now I think the site first store some cookie from the link1 and then only allow you to post data to link2 as whenever I try to open the link2 in incognito the site displays the error message "Session Timed out OR Maximum connections limit reached. Cannot Proceed Further. Please close and restart your browser "
Now I have tried this:
try
{
//Send the GET request
httpResponse = await httpClient.GetAsync(new Uri(link1UriString));
//Send the POSTrequest
httpResponse = await httpClient.PostAsync(new Uri(link2uriString),postContent);
httpResponseBody = await httpResponse.Content.ReadAsStringAsync();
}
But I am getting the session timed out error message. How to maintain cookies for a session in httpClient continuously received from the web.Like in python it can be done by
opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookielib.CookieJar()))
urllib2.install_opener(opener)
Link1
Link2
You can use a CookieContainer to handle cookies for you.
Doing so, you'd create the HttpClient like this.
using System.Net;
using System.Net.Http;
CookieContainer cookies = new CookieContainer();
HttpClientHandler handler = new HttpClientHandler();
handler.CookieContainer = cookies;
HttpClient httpClient = new HttpClient(handler);
httpResponse = await httpClient.GetAsync(new Uri(link1UriString));
(Note it uses the version of HttpClient in System.Net.Http)
So, after first response you have Set-Cookie header:
var responseMessage = await httpClient.GetAsync("http://115.248.50.60/registration/Main.jsp?wispId=1&nasId=00:15:17:c8:09:b1");
IEnumerable<string> values;
var coockieHeader = string.Empty;
if (responseMessage.Headers.TryGetValues("set-cookie", out values))
{
coockieHeader = string.Join(string.Empty, values);
}
After that, just setup your cookie into request message:
var httpRequestMessage = new HttpRequestMessage
{
RequestUri = new Uri("http://115.248.50.60/registration/chooseAuth.do"),
Content = postContent,
Method = HttpMethod.Post
};
httpRequestMessage.Headers.Add("Cookie", values);
var httpResponse = await httpClient.SendAsync(httpRequestMessage);

Jasper server rest service returns unauthorized

Using .NET Http client i login to jasper server.
HttpResponseMessage loginResponse = loginClient.PostAsync("http://localhost:8080/jasperserver/rest/login", formContent).Result;
IEnumerable<string> jaspsessid = loginResponse.Headers.GetValues("Set-Cookie");
Using above session id i pass to next request.
HttpClient httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Add("Cookie", jaspsessid);
httpClient.DefaultRequestHeaders.Accept.Add(new
System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
StringContent requestContent = constructJasperRequestJson(reportParameters);
HttpResponseMessage generateReportRequestResponse = new HttpResponseMessage();
generateReportRequestResponse = httpClient.PostAsync(AppConstant.JASPER_SERVER_BASE_URI + AppConstant.JASPER_SERVER_REPORT_EXECUTION_URI, requestContent).Result;
In second request i am getting 401.Unauthorized.
If anyone knows the issue,help me.
You could use a CookieContainer to hold the session cookie, rather than setting a header.
See How do I set a cookie on HttpClient's HttpRequestMessage for an example.

C# how to pass query string parameters in a post call

I have to call an external rest service from wpf application. I do not have any control on the service. When I make a request to the service using a rest client (e.g. Postman) it works fine i.e. success is returned. A post call is done to this URL:
http://mydomain.com:38080/workshop/rest/login?username=usr&password=pwd
You can see that I have to pass username and password in querystring.
But when I do the same from my application the service returns failed. Here is my code:
string EndPoint = "http://mydomain.com:38080/workshop/";
string parameters = "username=usr&password=pwd";
CookieContainer cookies = new CookieContainer();
HttpClientHandler handler = new HttpClientHandler();
handler.CookieContainer = cookies;
HttpClient client = new HttpClient(handler);
client.BaseAddress = new Uri(EndPoint);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = client.PostAsync("rest/login", new StringContent(parameters)).Result;
Task task = response.Content.ReadAsStreamAsync().ContinueWith(t =>
{
var stream = t.Result;
using (var reader = new StreamReader(stream))
{
responseValue = reader.ReadToEnd();
}
});
task.Wait();
It seems that the service is expecting parameters in querystring whereas my code is passing them in request header. So how do I pass the parameters in querystring in a post call?

Issue with reproducing the results of a cURL command in code

I am trying to do the following using .NET
What would the C# code look like using HttpClient, if my username is test and password is password?
HTTP Method: GET
URL: http://webapi.ebayclassifieds.com/webapi/categories
Sample command:
curl --digest -u{username}:{password} http://webapi.ebayclassifieds.com/webapi/categories
Here is what I have but I don't get the html:
var client = new HttpClient();
var requestContent = new FormUrlEncodedContent(new[] {
new KeyValuePair<string, string>("-u", "{test}:{password}") });
HttpResponseMessage response = await client.PostAsync(
"http://webapi.ebayclassifieds.com/webapi/categories", requestContent);
// Get the response content.
HttpContent responseContent = response.Content;
var blah = response.Content.ReadAsStringAsync();
Try this one:
CredentialCache credCache = new CredentialCache();
credCache.Add (new Uri ("http://webapi.ebayclassifieds.com"), "Digest", new NetworkCredential ("username", "passwd"));
After that construct the HttpClient with the credential cache:
var httpClient = new HttpClient( new HttpClientHandler { Credentials = credCache});
Rest of the process is same. If you perform http POST then use PostAsync, and for http GET use GetAsync.
You'll find more detail about CredentialCache from here.

Categories

Resources