Call Api from WebClient() post To HttpClient() post with authentication Headers - c#

I have this code written in deprecated WebClient and I have to update using HttpClient.
The WebClient implementation works correctly but HttpClient no, where am I doing wrong?
using (var wb = new WebClient())
{
wb.Encoding = System.Text.Encoding.UTF8;
wb.Headers.Set(HttpRequestHeader.ContentType, "application/json");
wb.Headers.Add("user_key", "USER_KEY");
wb.Headers.Add("Session_key", "SESSION_KEY");
String payload = "{" +
" \"address\": \"via xxx\", " +
" \"cell\": \"+393393939393\", "
"}";
var response = wb.UploadString("https://..../API/subaccount", "POST", payload);
// OK
}
using (HttpClient cli = new())
{
String payload = "{" +
" \"address\": \"via xxx\", " +
" \"cell\": \"+393393939393\", "
"}";
cli.DefaultRequestHeaders.Accept.Clear();
cli.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
cli.DefaultRequestHeaders.Add("Authorization", "Basic ");
cli.DefaultRequestHeaders.Add("user_key", "USER_KEY");
cli.DefaultRequestHeaders.Add("Access_token", "SESSION_KEY");
var response = cli.PostAsJsonAsync("https://..../API/subaccount", payload).Result;
//StatusCode: 400, ReasonPhrase: 'Bad Request'
}

Related

Azure Storage Queue via REST API c# using Shared Key Authentication

I am trying to call Azure Storage queue using REST API, but I am getting an error
The MAC signature found in the HTTP request
'UCiypkoySXueF4scXt+EqQESf5VXmAVLJUA93+3W10M=' is not the same as any
computed signature. The server used following string to sign: 'POST
text/plain
My C# Code is
var Client = new HttpClient();
var RequestDateString = DateTime.UtcNow.ToString("R", CultureInfo.InvariantCulture);
if (Client.DefaultRequestHeaders.Contains("x-ms-date"))
Client.DefaultRequestHeaders.Remove("x-ms-date");
Client.DefaultRequestHeaders.Add("x-ms-date", RequestDateString);
var StorageAccountName = "storaxxxxxxxsnd";
var StorageKey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx==";
String urlPath = String.Format("{0}/messages", "splitator");
Uri uri = new Uri(string.Format("https://{0}.queue.core.windows.net/", StorageAccountName) + urlPath);
if (Client.DefaultRequestHeaders.Contains("Authorization"))
Client.DefaultRequestHeaders.Remove("Authorization");
var canonicalizedStringToBuild = string.Format("{0}\n{1}", RequestDateString, $"/{StorageAccountName}/{uri.AbsolutePath.TrimStart('/')}");
string signature;
using (var hmac = new HMACSHA256(Convert.FromBase64String(StorageKey)))
{
byte[] dataToHmac = Encoding.UTF8.GetBytes(canonicalizedStringToBuild);
signature = Convert.ToBase64String(hmac.ComputeHash(dataToHmac));
}
string authorizationHeader = string.Format($"{StorageAccountName}:" + signature);
Client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("SharedKey", authorizationHeader);
Client.DefaultRequestHeaders.Accept.Clear();
Client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("text/plain"));
if (Client.DefaultRequestHeaders.Contains("x-ms-version"))
Client.DefaultRequestHeaders.Remove("x-ms-version");
Client.DefaultRequestHeaders.Add("x-ms-version", "2015-12-11");
// if (httpMethod == HttpMethod.Delete || httpMethod == HttpMethod.Put)
// {
// if (Client.DefaultRequestHeaders.Contains("If-Match"))
// Client.DefaultRequestHeaders.Remove("If-Match");
// Currently I'm not using optimistic concurrency :-(
try
{
//Client.DefaultRequestHeaders.Add("If-Match", "*");
var stringContent = new StringContent("TESTAUTH", Encoding.UTF8, "text/plain");
var response= Client.PostAsync(uri, stringContent);
var resu=response.Result;
}
catch(Exception ex)
{
}
I am not sure what I am missing. I tried various combination but its failing.
I tried Microsoft recommended stringToSign formula too
I tried using canonical headers too
string signature;
var stringTosign = "POST\n" + "\n" + "\n" + "1024" + "\n" + "\n" + "text/plain\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + dateInRfc1123Format + "/xxxxxx/splitator/messages";
var hmac = new HMACSHA256(Convert.FromBase64String(accountKey));
var headerval= accountName + ":" + Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(stringTosign)));
Client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("SharedKey", headerval);
Client.DefaultRequestHeaders.Accept.Clear();
I fixed the issue in your code, and now it's working. Please give it a try:
namespace ConsoleApp25
{
class Program
{
static void Main(string[] args)
{
var Client = new HttpClient();
var StorageAccountName = "yy1";
var StorageKey = "xxxx";
var apiversion = "2020-02-10";
var queue_name = "myqueue2";
String urlPath = String.Format("{0}/messages", queue_name);
Uri uri = new Uri(string.Format("https://{0}.queue.core.windows.net/{1}", StorageAccountName, urlPath));
//define a message to send
string raw_message = "TESTAUTH is ok";
//to send the message to the queue storage, the raw message must be formatted as below
string queue_message = $"<QueueMessage><MessageText>{raw_message}</MessageText></QueueMessage>";
//define the content type
string content_type = "text/plain; charset=utf-8";
//define date
var RequestDateString = DateTime.UtcNow.ToString("R", CultureInfo.InvariantCulture);
string StringToSign = String.Format("POST\n"
+ "\n" // content encoding
+ "\n" // content language
+ queue_message.Length + "\n" // content length
+ "\n" // content md5
+ content_type +"\n" // content type
+ "\n" // date
+ "\n" // if modified since
+ "\n" // if match
+ "\n" // if none match
+ "\n" // if unmodified since
+ "\n" // range
+ "x-ms-date:" + RequestDateString + "\nx-ms-version:" + apiversion + "\n" // headers
+ "/{0}/{1}/{2}", StorageAccountName, queue_name, "messages"); //url
string auth = SignThis(StringToSign, StorageKey, StorageAccountName);
//define authorization header
if (Client.DefaultRequestHeaders.Contains("Authorization"))
Client.DefaultRequestHeaders.Remove("Authorization");
Client.DefaultRequestHeaders.Add("Authorization", auth);
Client.DefaultRequestHeaders.Accept.Clear();
//define x-ms-version header
Client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("text/plain"));
if (Client.DefaultRequestHeaders.Contains("x-ms-version"))
Client.DefaultRequestHeaders.Remove("x-ms-version");
Client.DefaultRequestHeaders.Add("x-ms-version", apiversion);
//define the x-ms-date header
if (Client.DefaultRequestHeaders.Contains("x-ms-date"))
Client.DefaultRequestHeaders.Remove("x-ms-date");
Client.DefaultRequestHeaders.Add("x-ms-date", RequestDateString);
try
{
var stringContent = new StringContent(queue_message, Encoding.UTF8, "text/plain");
var response = Client.PostAsync(uri, stringContent);
var resu = response.Result;
}
catch (Exception ex)
{
}
Console.WriteLine("**completed**");
Console.ReadLine();
}
private static String SignThis(String StringToSign, string Key, string Account)
{
String signature = string.Empty;
byte[] unicodeKey = Convert.FromBase64String(Key);
using (HMACSHA256 hmacSha256 = new HMACSHA256(unicodeKey))
{
Byte[] dataToHmac = System.Text.Encoding.UTF8.GetBytes(StringToSign);
signature = Convert.ToBase64String(hmacSha256.ComputeHash(dataToHmac));
}
String authorizationHeader = String.Format(
CultureInfo.InvariantCulture,
"{0} {1}:{2}",
"SharedKey",
Account,
signature);
return authorizationHeader;
}
}
}
And if you don't want to generate the shared key since it's not easy, you can use sas token for authentication in the rest api.

http request put not working with json format

I am trying to call an update api with the given parameter at the end of the url, however the update was unsuccessful and returns me an exception.
Here is my sample code for PUT method:
string result = "";
string json = "{" +
"\"ID\": " + 343336 + ", " +
"\"occurence\": " + 0 + ", " +
"\"user\": " + "Juan Dela Cruz" + ", " +
"\"comments\":" + "Test comments" +
"}";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://myurl/Update/343336");
request.Method = "PUT";
request.ContentType = "application/json";
using (var streamWriter = new StreamWriter(request.GetRequestStream()))
{
streamWriter.Write(json);
streamWriter.Flush();
streamWriter.Close();
HttpWebResponse httpResponse;
try
{
httpResponse = (HttpWebResponse)request.GetResponse();
}
catch (WebException ex)
{
httpResponse = (HttpWebResponse)ex.Response;
}
using (StreamReader reader = new StreamReader(httpResponse.GetResponseStream(), Encoding.UTF8))
{
result = reader.ReadToEnd();
}
}
console.WriteLine(result);
I already put a try catch on my code and it was returning me this error:
Unrecognized token: was expecting (true, false or null)
Any comments/suggestions TIA.

Unauthorized exception while generating access token using client_Id and client_secret for sharepoint

I am using a c# code to generate access token for my sharepoint site, using client ID and Client Secret.When I am writing the response using HttpWebResponse I am getting 401:Unauthorized.
I have already generated access token using this code and it worked fine. Now I am getting exception in
var response = (HttpWebResponse)myWebRequest.GetResponse();
CommonUtility.stGetAccessTokenUrl = string.Format(CommonUtility.stGetAccessTokenUrl, CommonUtility.tenantID);
myWebRequest = WebRequest.Create(CommonUtility.stGetAccessTokenUrl);
myWebRequest.ContentType = "application/x-www-form-urlencoded";
myWebRequest.Method = "POST";
// Add the below body attributes to the request
/*
* grant_type client_credentials client_credentials
client_id ClientID#TenantID
client_secret ClientSecret
resource resource/SiteDomain#TenantID resourceid/abc.sharepoint.com#tenantID
*/
var postData = "grant_type=client_credentials";
postData += "&client_id=" + CommonUtility.stClientID + "#" + CommonUtility.tenantID;
postData += "&client_secret=" + (CommonUtility.stClientSecret);
postData += "&resource=" + CommonUtility.resourceID + "/" + CommonUtility.stSiteDomain + "#" + CommonUtility.tenantID;
var data = Encoding.ASCII.GetBytes(postData);
using (var stream = myWebRequest.GetRequestStream())
{
stream.Write(data, 0, data.Length);
}
var response = (HttpWebResponse)myWebRequest.GetResponse();
var responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();
string[] stArrResponse = responseString.Split(',');
//get the access token and expiry time ,etc
foreach (var stValues in stArrResponse)
{
if (stValues.StartsWith("\"access_token\":"))
{
//Console.WriteLine(" Result => " + stValues);
accessToken = stValues.Substring(16);
//Console.WriteLine(" Result => " + accessToken);
accessToken = accessToken.Substring(0, accessToken.Length - 2);
// Console.WriteLine(" Result => " + accessToken);
}
}
I have changed client Id and client secret only and it started to give me unauthorized exception. Could anyone help with this?

Converting WebClient to HttpClient

I have been surfing and working on this for hours now and I'm read to throw my PC.
I have a WebClient on WPF application that needs to be converted to HttpClient for UWP application. I am getting a lot of header errors and since I'm not a web guru I am beating myself.
Here's the original and if someone would be extremely kind and help me convert it to HttpClient I would be very thankful.
using (var client = new WebClient())
{
string request = "------WebKitFormBoundarygWsJMIUcbjwBPfeL"
+ Environment.NewLine
+ "Content-Disposition: form-data; name=\"guid\""
+ Environment.NewLine
+ Environment.NewLine
+ presetSmall.PresetId.ToString()
+ Environment.NewLine
+ "------WebKitFormBoundarygWsJMIUcbjwBPfeL"
+ Environment.NewLine
+ "Content-Disposition: form-data; name=\"delay\""
+ Environment.NewLine
+ Environment.NewLine
+ "0"
+ Environment.NewLine
+ "------WebKitFormBoundarygWsJMIUcbjwBPfeL--"
+ Environment.NewLine;
client.Headers.Add(HttpRequestHeader.ContentType, "multipart/form-data; boundary=----WebKitFormBoundarygWsJMIUcbjwBPfeL");
client.UploadStringAsync(new Uri(ServerName + UriForPresetExecution), "POST", request);
}
The problem is in the client.Headers.Add method... I cannot for the sake of time figure out how HttpClient wants me to add those headers.
Please try this:
using System.Net.Http;
using System.Net.Http.Headers;
using (var httpClient = new HttpClient())
{
var httpContent = new StringContent(request);
httpContent.Headers.Clear();
httpContent.Headers.Add("Content-Type", "multipart/form-data; boundary=----WebKitFormBoundarygWsJMIUcbjwBPfeL");
var response = await httpClient.PostAsync(requestUri, httpContent);
}

A JSONObject text must begin with '{' at character 0 of "} when posting data using C#

I am trying to multipart a rest web service using C# from my Windows Phone.
For this I am using the httpClient.
Even if the string I am sending is this:
{"AuthenticationRequest":{"company":"3000","identificationCode":"111", "username":"jack","password":"paz"}}
I am receiving this message description in my response body:
A JSONObject text must begin with '{' at character 0 of "}
Here is my code:
public async Task postHttpClient(string serviceUrl, string requestObj)
{
try
{
var client = new HttpClient();
client.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "multipart/form-data");
MultipartFormDataContent content = new MultipartFormDataContent();
Debug.WriteLine("requestObject: " + requestObject);
content.Add(new StringContent(requestObj, Encoding.UTF8), "AuthenticationRequest");
var responseVar = await client.PostAsync(serviceUrl, content);
responseVar.EnsureSuccessStatusCode();
Debug.WriteLine("responseVar: " + responseVar.ToString());
var body = await responseVar.Content.ReadAsStringAsync();
Debug.WriteLine("body: " + body);
}
catch (Exception e)
{
Debug.WriteLine("e: " + e.ToString());
}
}
Please what am I doing wrong?
Note: the first letter of my variable is { as obtained by
Debug.WriteLine("first letter: " + requestObj[0]);
I also trimmed that variable with no changes.
It might have to do with your service expecting application/json content and you are sending multipart/form-data.
Try this:
var message = new HttpRequestMessage(HttpMethod.Post, new Uri(serviceUrl));
message.Content = new StringContent(json, Encoding.UTF8, "application/json");
var result = await client.SendAsync(message, cancellationToken);

Categories