C# WebRequest removes Authorization header on GET request - c#

I'm trying to communicate with some server but the Authorization header gets removed when I use a GET request.
My code (please excuse the mess):
public ApiResponse MakeApiRequest(string path, string body, Dictionary<string, string> header,
Dictionary<string, string> query, string method)
{
var queryBuilder = new StringBuilder("?");
foreach (var queryPair in query)
{
queryBuilder.Append(queryPair.Key + "=" + queryPair.Value + "&");
}
var queryString = queryBuilder.ToString();
queryString = queryString.Substring(0, queryString.Length - 1);
var request = (HttpWebRequest) WebRequest.Create(new Uri(ApiServer + path + queryString));
request.Timeout = 5000;
request.UserAgent = "VSpedSync/DevBuild";
request.Method = method;
foreach (var headerPair in header)
{
if (headerPair.Key.ToLower().Equals("user-agent")) continue;
if (headerPair.Key.ToLower().Equals("authorization"))
{
request.PreAuthenticate = true;
}
request.Headers.Add(headerPair.Key, headerPair.Value);
}
Debug.WriteLine("preauth "+request.PreAuthenticate);
if (!body.Equals(""))
{
var stream = request.GetRequestStream();
var streamWriter = new StreamWriter(stream);
streamWriter.Write(body);
streamWriter.Close();
}
HttpWebResponse response;
try
{
response = (HttpWebResponse) request.GetResponse();
}
catch (WebException ex)
{
response = (ex.Response as HttpWebResponse);
if (response == null)
throw;
}
foreach (string requestHeader in request.Headers)
{
Debug.WriteLine(" --> "+requestHeader+": "+request.Headers.Get(requestHeader));
}
var statusCode = response.StatusCode;
var responseHeaders = new Dictionary<string, string>();
foreach (string headerKey in response.Headers)
{
var headerVal = response.Headers.Get(headerKey);
responseHeaders.Add(headerKey, headerVal);
}
var responseBody = "NONE";
try
{
var streamReader = new StreamReader(response.GetResponseStream());
responseBody = streamReader.ReadToEnd();
}
catch (Exception)
{
responseBody = "ERROR";
// ignored
}
return new ApiResponse(
statusCode,
responseBody,
!responseBody.Equals("ERROR") && !responseBody.Equals("NONE"),
responseHeaders
);
}
This is how I call the method:
var apiResponse = api.MakeApiRequest("auth/check/", "", new Dictionary<string, string>()
{
{"Authorization", "Bearer " + token.token},
{"test", "f"}
}, new Dictionary<string, string>(), "GET");
The headers that are sent when I use the GET method:
--> User-Agent: VSpedSync/DevBuild
--> test: f
--> Host: localhost:55445
The headers that are sent when I use the POST method:
--> User-Agent: VSpedSync/DevBuild
--> Authorization: Bearer xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
--> test: f
--> Host: localhost:55445
Am I doing something wrong?
Edit: Seems to be solved. I'm using RestSharp now instead of the normal WebRequest.

You can try to use the HttpClient instead of the WebRequest. I tried the following and the authorization header stayed in the request after sending it.
const string ApiServer = "https://google.com";
static readonly HttpClient _httpClient = new HttpClient();
static async Task Main()
{
InitializeClient();
var headers = new Dictionary<string, string>()
{
{ "Authorization", "Bearer e45jsh56" },
{ "Test", "test_value" }
};
var paramterers = new Dictionary<string, string>()
{
{ "pageNum", "3" },
{ "pageSize", "100" }
};
var response = await MakeApiCallAsync("mypath", "request_body", headers, paramterers, "GET");
Console.WriteLine($"Status Code: {response.StatusCode}.");
}
static void InitializeClient()
{
// Set the base URI
_httpClient.BaseAddress = new Uri(ApiServer);
// Set Timeout to 5 seconds
_httpClient.Timeout = new TimeSpan(hours: 0, minutes: 0, seconds: 5);
// Set the default User Agent
_httpClient.DefaultRequestHeaders.UserAgent.ParseAdd("VSpedSync/DevBuild");
}
static async Task<ApiResponse> MakeApiCallAsync(string path,
string body, Dictionary<string, string> headers,
Dictionary<string, string> query, string method)
{
// Generate query string
string queryString = '?' +
string.Join(separator: '&', values: query.Select(q => $"{q.Key}={q.Value}"));
// Create the relative URL
string relativeUrl = path + queryString;
// Create the Http Method object
HttpMethod httpMethod = new HttpMethod(method);
// Create the request object
HttpRequestMessage request = new HttpRequestMessage(httpMethod, relativeUrl);
// Set headers to the request
foreach (KeyValuePair<string, string> h in headers)
{
if (!h.Key.Equals("UserAgent", StringComparison.OrdinalIgnoreCase))
{
request.Headers.Add(h.Key, h.Value);
}
}
// Set the content of the request
if (!string.IsNullOrEmpty(body))
{
request.Content = new StringContent(body);
}
// Send the request
HttpResponseMessage response = await _httpClient.SendAsync(request);
// Display request headers
foreach(var h in request.Headers)
{
Console.WriteLine($" --> {h.Key}: {string.Join(';', h.Value)}.");
}
// Process the response body
string responseBody = "NONE";
try
{
// Read the content as a string
responseBody = await response.Content.ReadAsStringAsync();
}
catch
{
responseBody = "ERROR";
}
// Return the api response
return new ApiResponse
{
StatusCode = response.StatusCode,
ResponseBody = responseBody,
ValidResponse = !responseBody.Equals("NONE") && !responseBody.Equals("ERROR"),
ResponseHeaders = response.Headers.ToDictionary(h => h.Key, h => string.Join(';', h.Value)),
};
}
Output
--> Authorization: Bearer e45jsh56.
--> Test: test_value.
--> User-Agent: VSpedSync/DevBuild.
Status Code: BadRequest.

Maybe try to use the WebHeaderCollection.Add(HttpRequestHeader, String) overload method.
public static ApiResponse MakeApiRequest(string path, string body, Dictionary<string, string> headers,
Dictionary<string, string> query, string method)
{
// Generate the query string
string queryString = '?' +
string.Join(separator: '&', values: query.Select(q => $"{q.Key}={q.Value}"));
// Create request obejct
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(new Uri(ApiServer + path + queryString));
request.Timeout = 5000;
request.UserAgent = "VSpedSync/DevBuild";
request.Method = method;
// Set headers to the request
foreach (KeyValuePair<string, string> h in headers)
{
if (h.Key.Equals("Authorization", StringComparison.OrdinalIgnoreCase))
{
request.Headers.Add(HttpRequestHeader.Authorization, h.Value);
}
else if (!h.Key.Equals("UserAgent", StringComparison.OrdinalIgnoreCase))
{
request.Headers.Add(h.Key, h.Value);
}
}
foreach (string requestHeader in request.Headers)
{
Debug.WriteLine(" --> " + requestHeader + ": " + request.Headers.Get(requestHeader));
}
// ...
// .... Continue ....
// ...
return null;
}

Related

Unauthorized status from mobile Xamarin Forms application with Axelor Rest web-services

I want to connect to the Axelor server with a Xamarin forms application, I use this method to test the rest services connectivity :
Login login = new()
{
UserName = Constants.Login,
Password = Constants.Password
};
// Build authentication string
byte[] bytes = Encoding.UTF8.GetBytes($"{login.UserName}:{login.Password}");
string authorizationString = Convert.ToBase64String(bytes);
// Add headers to the HTTP client
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", authorizationString);
// Build HTTP message and send, strRoot = login.jsp
string url = $"{Constants.RestBaseUrl}/{strRoot}";
HttpRequestMessage message = new HttpRequestMessage(HttpMethod.Post, url);
var sessionResponse = await httpClient.SendAsync(message);
/* sessionResponse.IsSuccessStatusCode = true, and sessionResponse.Headers =
{
Set-Cookie: JSESSIONID=E5EA31C3A5CBDF0A1C4B05ED2230679E; Path=/Gradle___com_axelor___axelor_erp_6_3_0_war; HttpOnly
Date: Mon, 14 Nov 2022 19:40:04 GMT
}
*/
sessionResponse.Headers.ToList().ForEach(x =>
httpClient.DefaultRequestHeaders.Add(x.Key, x.Value.FirstOrDefault()));
var rt = $"{Constants.RestBaseUrl}/ws/rest/com.axelor.apps.poultryfarming.db.Hatchery";
var response = await httpClient.GetAsync(rt);
var returnValue = await response.Content.ReadAsStringAsync();
/* returnValue :
<!doctype html><html lang="en"><head><title>HTTP Status 401 – Unauthorized</title><style type="text/css">body {font-family:Tahoma,Arial,sans-serif;} h1, h2, h3, b {color:white;background-color:#525D76;} h1 {font-size:22px;} h2 {font-size:16px;} h3 {font-size:14px;} p {font-size:12px;} a {color:black;} .line {height:1px;background-color:#525D76;border:none;}</style></head><body><h1>HTTP Status 401 – Unauthorized</h1><hr class="line" /><p><b>Type</b> Status Report</p><p><b>Description</b> The request has not been applied because it lacks valid authentication credentials for the target resource.</p><hr class="line" /><h3>Apache Tomcat/8.5.73</h3></body></html>
*/
var stat = response.StatusCode; // return: Unauthorized
var cc = response.IsSuccessStatusCode;
return returnValue;
}
catch (Exception e)
{
throw;
}
but i always get the Unauthorized status !
Can you help me please
When I test with navigator I have correct response like this :
It works well with RestSharp.RestRequest!
Call Axelor rest services with RestClient example : https://github.com/dalmed/Maui-Axelor-Mobile.git
This is my solution :
public class RestClientService : IRestClientService
{
//private readonly ILogger<RestClientService> _logger;
public RestClientService()
{
//_logger = logger;
}
public async Task<bool> LoginAsync(Login login)
{
string jsonString = JsonSerializer.Serialize(login);
try
{
Constants.Cookies = null;
Constants.IsServerConnected = false;
var uri = new Uri($"{Constants.RestBaseUrl}/login.jsp");
var _RestClient = new RestClient(uri);
var request = new RestRequest(uri, Method.Post);
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", login, ParameterType.RequestBody);
RestResponse response = await _RestClient.ExecuteAsync(request);
if (response.IsSuccessStatusCode)
{
Constants.Cookies = response.Cookies;
Constants.IsServerConnected = true;
}
return response.IsSuccessStatusCode;
}
catch (Exception e)
{
// _logger.LogError(e, "LoginError");
throw;
}
}
public async Task<RootData<T>> RestServiceGetAsync<T>(string model, int offset = 0, int limit = 10)
{
try
{
var uri = $"{Constants.RestBaseUrl}/ws/rest/{model}";
var _RestClient = new RestClient(uri);
var request = new RestRequest(uri, Method.Get);
request.AddHeader("Content-Type", "application/json");
if (Constants.Cookies.Any() && Constants.IsServerConnected)
{
string cookie = "";
Constants.Cookies.ToList().ForEach(x => cookie += $"{x.Name}={x.Value}; ");
request.AddHeader("Cookie", cookie);
}
else
{
throw new Exception("The server is not connected !");
}
request.AddParameter("offset", offset, ParameterType.UrlSegment);
request.AddParameter("limit", limit, ParameterType.UrlSegment);
RestResponse response = await _RestClient.ExecuteAsync(request);
if (response.IsSuccessStatusCode)
{
var data = new MemoryStream(Encoding.UTF8.GetBytes(response.Content));
var rslt = await JsonSerializer.DeserializeAsync<RootData<T>>(data);
return rslt;
}
return null;
}
catch (Exception e)
{
//_logger.LogError(e, $"GetModelError: {model}");
throw;
}
}
public async Task<bool> LogoutAsync()
{
try
{
var uri = $"{Constants.RestBaseUrl}/logout";
var _RestClient = new RestClient(uri);
var request = new RestRequest(uri, Method.Get);
request.AddHeader("Content-Type", "application/json");
if (Constants.Cookies.Any() && Constants.IsServerConnected)
{
string cookie = "";
Constants.Cookies.ToList().ForEach(x => cookie += $"{x.Name}={x.Value}; ");
request.AddHeader("Cookie", cookie);
}
else
{
throw new Exception("The server is not connected !");
}
RestResponse response = await _RestClient.ExecuteAsync(request);
return response.IsSuccessStatusCode;
}
catch (Exception e)
{
//_logger.LogError(e, "LogoutError");
throw;
}
}
}

How to create issue in jira using c#

I'm trying to create an issue in JIRA cloud using c# and the REST API,
I get the 400 error (bad rquest), I dont know what I'm doing wrong !
This is My functions
public static string PostJsonRequest(string endpoint, string userid, string password, string json)
{
// Create string to hold JSON response
string jsonResponse = string.Empty;
using (var client = new WebClient())
{
try
{
client.Encoding = System.Text.Encoding.UTF8;
client.Headers.Set("Authorization", "Basic " + GetEncodedCredentials(userid, password));
client.Headers.Add("Content-Type: application/json");
client.Headers.Add("Accept", "application/json");
var uri = new Uri(endpoint);
var response = client.UploadString(uri, "POST", json);
jsonResponse = response;
}
catch (WebException ex)
{
// Http Error
if (ex.Status == WebExceptionStatus.ProtocolError)
{
HttpWebResponse wrsp = (HttpWebResponse)ex.Response;
var statusCode = (int)wrsp.StatusCode;
var msg = wrsp.StatusDescription;
// throw new SmtpException(statusCode, msg);
}
else
{
// throw new HttpException(500, ex.Message);
}
}
}
return jsonResponse;
}
And this is my JSON
string json = #"{
'fields':
{
'project':
{
'key':'IS'
},
'summary':'REST Test',
'issuetype':
{
'name':'Bug'
},
}
}";
string Url = "https://XXXXXX.atlassian.net/rest/api/2/issue/";
Any Ideas on what I'm doing wrong ?

Get findMeetingTimes POST WebRequest

I am trying to make a POST call to findMeetingTimes using Microsoft Graph in C#
https://graph.microsoft.com/v1.0/users/{userid}/findMeetingTimes
To get user profile data, I have followings:
IUserProfile IUserAuthentication.GetProfileData(string accessToken)
{
MicrosoftUserProfile profile = new MicrosoftUserProfile();
try
{
string url = "https://graph.microsoft.com/v1.0/me";
Dictionary<string, string> headers = new Dictionary<string, string>();
headers.Add("Authorization", "Bearer " + accessToken);
WebRequests webReq = new WebRequests();
string response = webReq.GetRequest(url, headers);
profile = JsonConvert.DeserializeObject<MicrosoftUserProfile>(response);
}
catch (Exception)
{
throw;
}
return profile;
}
public string GetRequest(string url, IDictionary<string, string> headers)
{
string returned = "";
try
{
System.Net.WebRequest webRequest = System.Net.WebRequest.Create(url);
webRequest.Method = "GET";
if (headers.Count > 0)
{
foreach (var item in headers)
{
webRequest.Headers.Add(item.Key, item.Value);
}
}
System.Net.WebResponse resp = webRequest.GetResponse();
System.IO.StreamReader sr = new System.IO.StreamReader(resp.GetResponseStream());
returned = sr.ReadToEnd().Trim();
}
catch (Exception)
{
throw;
}
return returned;
}
The best suggestion for you is to use the Microsoft Graph Client Library directly but not to use the HttpClient. After installing the library and then
just use the following code:
graphClient.Me.FindMeetingTimes().Request().PostAsync()
This is a simple and efficient way to make your code more readable.
Of course, you can write your own logic by imitating the following code:
// 1. Create request message with the URL for the trending API.
string requestUrl = "https://graph.microsoft.com/V1.0/me/findMeetingTimes";
HttpRequestMessage hrm = new HttpRequestMessage(HttpMethod.Post, requestUrl);
// 2. Authenticate (add access token) our HttpRequestMessage
graphClient.AuthenticationProvider.AuthenticateRequestAsync(hrm).GetAwaiter().GetResult();
// 3. Send the request and get the response.
HttpResponseMessage response = graphClient.HttpProvider.PostAsync(hrm).Result;
// 4. Get the response.
var content = response.Content.ReadAsStringAsync().Result;
JObject responseBody = JObject.Parse(content);
// 4. Get the array of objects from the 'value' key.
JToken arrayOfObjects = responseBody.GetValue("value");

postAsync with header and content c#

I need to postAsync with header and content together. In order to get access to a website through Console Application in C#. I have my headers as an HttpHeader object with variable name header and my content named newContent as a string object with __Token, return, Email and Password. Now what I want to do is add newContent to header and then use postAsync(url, header+content) to make my POST request.
public async static void DownloadPage(string url)
{
CookieContainer cookies = new CookieContainer();
HttpClientHandler handler = new HttpClientHandler();
handler.CookieContainer = cookies;
using (HttpClient client = new HttpClient(handler))
{
using (HttpResponseMessage response = client.GetAsync(url).Result)
{
//statusCode
CheckStatusCode(response);
//header
HttpHeaders headers = response.Headers;
//content
HttpContent content = response.Content;
//getRequestVerificationToken&createCollection
string newcontent = CreateCollection(content);
using(HttpResponseMessage response2 = client.PostAsync(url,))
}
}
}
public static string GenerateQueryString(NameValueCollection collection)
{
var array = (from key in collection.AllKeys
from value in collection.GetValues(key)
select string.Format("{0}={1}", WebUtility.UrlEncode(key), WebUtility.UrlEncode(value))).ToArray();
return string.Join("&", array);
}
public static void CheckStatusCode(HttpResponseMessage response)
{
if (response.StatusCode != HttpStatusCode.OK)
throw new Exception(String.Format(
"Server error (HTTP {0}: {1}).",
response.StatusCode,
response.ReasonPhrase));
else
Console.WriteLine("200");
}
public static string CreateCollection(HttpContent content)
{
var myContent = content.ReadAsStringAsync().Result;
HtmlNode.ElementsFlags.Remove("form");
string html = myContent;
var doc = new HtmlAgilityPack.HtmlDocument();
doc.LoadHtml(html);
var input = doc.DocumentNode.SelectSingleNode("//*[#name='__Token']");
var token = input.Attributes["value"].Value;
//add all necessary component to collection
NameValueCollection collection = new NameValueCollection();
collection.Add("__Token", token);
collection.Add("return", "");
collection.Add("Email", "11111111#hotmail.com");
collection.Add("Password", "1234");
var newCollection = GenerateQueryString(collection);
return newCollection;
}
I did the very same thing yesterday. I created a seperate class for my Console App and put the HttpClient stuff in there.
In Main:
_httpCode = theClient.Post(_response, theClient.auth_bearer_token);
In the class:
public long Post_RedeemVoucher(Response _response, string token)
{
string client_URL_voucher_redeem = "https://myurl";
string body = "mypostBody";
Task<Response> content = Post(null, client_URL_voucher_redeem, token, body);
if (content.Exception == null)
{
return 200;
}
else
return -1;
}
Then the call itself:
async Task<Response> Post(string headers, string URL, string token, string body)
{
Response _response = new Response();
try
{
using (HttpClient client = new HttpClient())
{
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, URL);
request.Content = new StringContent(body);
using (HttpResponseMessage response = await client.SendAsync(request))
{
if (!response.IsSuccessStatusCode)
{
_response.error = response.ReasonPhrase;
_response.statusCode = response.StatusCode;
return _response;
}
_response.statusCode = response.StatusCode;
_response.httpCode = (long)response.StatusCode;
using (HttpContent content = response.Content)
{
_response.JSON = await content.ReadAsStringAsync().ConfigureAwait(false);
return _response;
}
}
}
}
catch (Exception ex)
{
_response.ex = ex;
return _response;
}
}
I hope this points you in he right direction!
How about iterating over your Headers and adding them to the Content object:
var content = new StringContent(requestString, Encoding.UTF8);
// Iterate over current headers, as you can't set `Headers` property, only `.Add()` to the object.
foreach (var header in httpHeaders) {
content.Headers.Add(header.Key, header.Value.ToString());
}
response = client.PostAsync(Url, content).Result;
Now, they're sent in one method.
If you are still looking into this you can also add headers at the request level as well as the HttpClient level. This works for me:
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, URL);
request.Content = new StringContent(body);
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");

How to use Magento REST API from C#

Where can I find samples that show how to connect to the Magento REST API using C#?
I found was a php one which I could not figure out except a little.
Using a Dropbox OAuth sample I found on the net I tried to make it work for Magento:
private void button1_Click(object sender, RoutedEventArgs e)
{
var consumerKey = “xxxxxxxxxxxxx”;
var consumerSecret = “xxxxxxxxxxxxxxxx”;
var uri = new Uri("http://www.MagentoWebsite.com/oauth/token");
// Generate a signature
OAuthBase oAuth = new OAuthBase();
string nonce = oAuth.GenerateNonce();
string timeStamp = oAuth.GenerateTimeStamp();
string parameters;
string normalizedUrl;
string signature = oAuth.GenerateSignature(uri, consumerKey, consumerSecret,
String.Empty, String.Empty, “GET”, timeStamp, nonce, OAuthBase.SignatureTypes.HMACSHA1,
out normalizedUrl, out parameters);
signature = HttpUtility.UrlEncode(signature);
StringBuilder requestUri = new StringBuilder(uri.ToString());
requestUri.AppendFormat("?oauth_consumer_key={0}&", consumerKey);
requestUri.AppendFormat("oauth_nonce={0}&", nonce);
requestUri.AppendFormat("oauth_timestamp={0}&", timeStamp);
requestUri.AppendFormat("oauth_signature_method={0}&", “HMAC-SHA1");
requestUri.AppendFormat("oauth_version={0}&", “1.0");
requestUri.AppendFormat("oauth_signature={0}", signature);
var request = (HttpWebRequest)WebRequest.Create(new Uri(requestUri.ToString()));
request.Method = WebRequestMethods.Http.Get;
var response = request.GetResponse();
var queryString = new StreamReader(response.GetResponseStream()).ReadToEnd();
var parts = queryString.Split(’&’);
var token = parts[1].Substring(parts[1].IndexOf(’=’) + 1);
var tokenSecret = parts[0].Substring(parts[0].IndexOf(’=’) + 1);
queryString = String.Format("oauth_token={0}", token);
var authorizeUrl = “http://www.MagentoWebsite.com/admin/oauth_authorize?”+queryString;
Process.Start(authorizeUrl);
}
Unfortunately this returns a BAD REQUEST response.
I recently started a project for a C# REST API client for Magento that might help you out:
https://github.com/nickvane/Magento-RestApi
It's not yet feature complete, but the oauth authentication is implemented.
The code uses restsharp which has support for oauth authentication.
I had the same question but couldn't find the answer hence I spent a day to make it work. I share my code here and I hope it will help other people in the feature.
use the following code in an aspx page to get oAuth access
protected void Page_Load(object sender, EventArgs e)
{
string oauth_token = Request.QueryString["oauth_token"];
string oauth_verifier = Request.QueryString["oauth_verifier"];
if (string.IsNullOrEmpty(oauth_token) || string.IsNullOrEmpty(oauth_verifier))
{
BeginAuthorization();
}
else
{
Authorize(oauth_token,oauth_verifier);
}
}
private void Authorize(string oauth_token, string oauth_verifier)
{
var uri = new Uri(MagentoServer + "/oauth/token");
string oauth_token_secret = (string)Session["oauth_token_secret"];
OAuthBase oAuth = new OAuthBase();
string nonce = oAuth.GenerateNonce();
string timeStamp = oAuth.GenerateTimeStamp();
string parameters;
string normalizedUrl;
string signature = oAuth.GenerateSignature(uri, ConsumerKey, ConsumerSecret,
oauth_token,oauth_token_secret, "GET", timeStamp, nonce, OAuthBase.SignatureTypes.PLAINTEXT,
out normalizedUrl, out parameters);
StringBuilder sb = new StringBuilder("OAuth ");
sb.AppendFormat("oauth_verifier=\"{0}\",", oauth_verifier);
sb.AppendFormat("oauth_token=\"{0}\",", oauth_token);
sb.AppendFormat("oauth_version=\"{0}\",", "1.0");
sb.AppendFormat("oauth_signature_method=\"{0}\",", "PLAINTEXT");
sb.AppendFormat("oauth_nonce=\"{0}\",", nonce);
sb.AppendFormat("oauth_timestamp=\"{0}\",", timeStamp);
sb.AppendFormat("oauth_consumer_key=\"{0}\",", ConsumerKey);
sb.AppendFormat("oauth_signature=\"{0}\"", signature);
var request = (HttpWebRequest)WebRequest.Create(uri);
request.Headers[HttpRequestHeader.Authorization] = sb.ToString();
request.ContentType = "text/xml";
request.Accept = "text/xml";
request.KeepAlive = true;
request.Method = "POST";
try
{
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
if (response.StatusCode == HttpStatusCode.OK)
{
Stream responseStream = response.GetResponseStream();
StreamReader responseReader = new StreamReader(responseStream);
string text = responseReader.ReadToEnd();
try
{
Dictionary<String, string> responseDic = GetDictionaryFromQueryString(text);
string token = responseDic.First(q => q.Key == "oauth_token").Value;
string secret = responseDic.First(q => q.Key == "oauth_token_secret").Value;
Configuration objConfig = System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration("~");
AppSettingsSection objAppsettings = (AppSettingsSection)objConfig.GetSection("appSettings");
//Edit
if (objAppsettings != null)
{
objAppsettings.Settings["Magento.Token"].Value = token;
objAppsettings.Settings["Magento.TokenSecret"].Value = secret;
objConfig.Save();
}
errorLabel.Text = "Done";
errorLabel.ForeColor = System.Drawing.Color.Green;
}
catch (Exception ex)
{
errorLabel.Text = "Exchanging token failed.<br>Response text = " + text + "<br>Exception = " + ex.Message;
}
}
}
catch (WebException ex)
{
var responseStream = ex.Response.GetResponseStream();
StreamReader responseReader = new StreamReader(responseStream);
string resp = responseReader.ReadToEnd();
errorLabel.Text = resp;
}
}
private void BeginAuthorization()
{
string CallbackUrl = Server.UrlEncode(Request.Url.AbsoluteUri);
var uri = new Uri(MagentoServer + "/oauth/initiate?oauth_callback=" + CallbackUrl);
OAuthBase oAuth = new OAuthBase();
string nonce = oAuth.GenerateNonce();
string timeStamp = oAuth.GenerateTimeStamp();
string parameters;
string normalizedUrl;
string signature = oAuth.GenerateSignature(uri, ConsumerKey, ConsumerSecret,
String.Empty, String.Empty, "GET", timeStamp, nonce, OAuthBase.SignatureTypes.PLAINTEXT,
out normalizedUrl, out parameters);
StringBuilder sb = new StringBuilder("OAuth ");
sb.AppendFormat("oauth_callback=\"{0}\",", CallbackUrl);
sb.AppendFormat("oauth_version=\"{0}\",", "1.0");
sb.AppendFormat("oauth_signature_method=\"{0}\",", "PLAINTEXT");
sb.AppendFormat("oauth_nonce=\"{0}\",", nonce);
sb.AppendFormat("oauth_timestamp=\"{0}\",", timeStamp);
sb.AppendFormat("oauth_consumer_key=\"{0}\",", ConsumerKey);
sb.AppendFormat("oauth_signature=\"{0}\"", signature);
var request = (HttpWebRequest)WebRequest.Create(uri);
request.Headers[HttpRequestHeader.Authorization] = sb.ToString();
request.ContentType = "text/xml";
request.Accept = "text/xml";
request.KeepAlive = true;
request.Method = "GET";
try
{
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
if (response.StatusCode == HttpStatusCode.OK)
{
Stream responseStream = response.GetResponseStream();
StreamReader responseReader = new StreamReader(responseStream);
string text = responseReader.ReadToEnd();
try
{
Dictionary<String, string> dic = GetDictionaryFromQueryString(text);
string oauth_token = dic.First(q => q.Key == "oauth_token").Value;
string oauth_token_secret = dic.First(q => q.Key == "oauth_token_secret").Value;
Session["oauth_token_secret"] = oauth_token_secret;
string redirectUrl = MagentoServer + "/index.php/admin/oauth_authorize?oauth_token=" + oauth_token + "&oauth_verifier=" +
oauth_token_secret;
Response.Redirect(redirectUrl);
}
catch (Exception ex)
{
errorLabel.Text = "Parsing request token failed.<br>Response text = " + text + "<br>Exception = " + ex.Message;
}
}
}
catch (WebException ex)
{
var responseStream = ex.Response.GetResponseStream();
StreamReader responseReader = new StreamReader(responseStream);
string resp = responseReader.ReadToEnd();
errorLabel.Text = resp;
}
}
private static Dictionary<string, string> GetDictionaryFromQueryString(string queryString)
{
string[] parts = queryString.Split('&');
Dictionary<String, string> dic = new Dictionary<string, string>();
foreach (var part in parts)
{
dic.Add(part.Split('=')[0], part.Split('=')[1]);
}
return dic;
}
#region Settings
string MagentoServer
{
get
{
return ConfigurationManager.AppSettings["Magento.Server"];
}
}
string ConsumerKey
{
get
{
return ConfigurationManager.AppSettings["Magento.ConsumerKey"];
}
}
string ConsumerSecret
{
get
{
return ConfigurationManager.AppSettings["Magento.ConsumerSecret"];
}
}
#endregion
}
add the following code in a class file
public class ApiClient
{
public ApiClient(string magentoServer, string consumerKey, string consumerSecret, string accessToken, string accessTokenSeccret)
{
MagentoServer = magentoServer;
ConsumerKey = consumerKey;
ConsumerSecret = consumerSecret;
AccessToken = accessToken;
AccessTokenSecret = accessTokenSeccret;
}
#region Request
HttpWebRequest CreateAuthorizedRequest(string url, string requestMethod,ApiFilter filter)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url + "?" + filter.ToString());
OAuthBase oAuth = new OAuthBase();
string nonce = oAuth.GenerateNonce();
string timeStamp = oAuth.GenerateTimeStamp();
string parameters;
string normalizedUrl;
string signature = oAuth.GenerateSignature(new Uri(url), ConsumerKey, ConsumerSecret,
AccessToken, AccessTokenSecret, requestMethod, timeStamp, nonce, OAuthBase.SignatureTypes.PLAINTEXT,
out normalizedUrl, out parameters);
StringBuilder sb = new StringBuilder("OAuth ");
sb.AppendFormat("oauth_token=\"{0}\",", AccessToken);
sb.AppendFormat("oauth_version=\"{0}\",", "1.0");
sb.AppendFormat("oauth_signature_method=\"{0}\",", "PLAINTEXT");
sb.AppendFormat("oauth_nonce=\"{0}\",", nonce);
sb.AppendFormat("oauth_timestamp=\"{0}\",", timeStamp);
sb.AppendFormat("oauth_consumer_key=\"{0}\",", ConsumerKey);
sb.AppendFormat("oauth_signature=\"{0}\"", signature);
request.Headers[HttpRequestHeader.Authorization] = sb.ToString();
request.Method = requestMethod;
//request.ContentType = "application/json";
request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";//application/json,
request.KeepAlive = true;
return request;
}
string FetchRequest(HttpWebRequest request)
{
try
{
string responseText = string.Empty;
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
if (response.StatusCode == HttpStatusCode.OK)
{
using (Stream responseStream = response.GetResponseStream())
{
using (StreamReader responseReader = new StreamReader(responseStream))
{
responseText = responseReader.ReadToEnd();
return responseText;
}
}
}
return responseText;
}
catch (WebException ex)
{
var responseStream = ex.Response.GetResponseStream();
StreamReader responseReader = new StreamReader(responseStream);
string responseText = responseReader.ReadToEnd();
throw new MagentoApiException(responseText,ex.Status);
}
}
#endregion
#region Public properties
string MagentoServer { get; set; }
string ConsumerKey { get; set; }
string ConsumerSecret { get; set; }
string AccessToken { get; set; }
string AccessTokenSecret { get; set; }
#endregion
}
public class ApiFilter
{
public ApiFilter()
{
filterDescriptions = new List<FilterDescription>();
}
public int? Page { get; set; }
public int? Limit { get; set; }
public List<FilterDescription> filterDescriptions;
public const string Type = "rest";
public void AddFilter(string column, FilterType filterType, string value)
{
filterDescriptions.Add(new FilterDescription()
{
Column = column,
FilterType = filterType,
Value = value
});
}
public override string ToString()
{
StringBuilder sb = new StringBuilder();
sb.AppendFormat("type={0}", Type);
if (Page.HasValue)
sb.AppendFormat("&page={0}", Page.Value);
if (Limit.HasValue)
sb.AppendFormat("&limit={0}", Limit.Value);
int counter = 1;
foreach (var filter in filterDescriptions)
{
sb.AppendFormat("&filter[{0}][attribute]={1}&filter[{2}][{3}]={4}", counter, filter.Column, counter, filter.FilterType, filter.Value);
counter++;
}
return sb.ToString();
}
}
public class FilterDescription
{
public string Column { get; set; }
public FilterType FilterType { get; set; }
public string Value { get; set; }
}
public enum FilterType
{
/// <summary>
/// Not Equal To
/// </summary>
neq,
/// <summary>
/// equals any of
/// </summary>
#in,
/// <summary>
/// not equals any of
/// </summary>
nin,
/// <summary>
/// greater than
/// </summary>
gt,
/// <summary>
/// less than
/// </summary>
lt
}
public class MagentoApiException : Exception
{
public MagentoApiException(string responseText, WebExceptionStatus status)
{
ResponseText = responseText;
Status = status;
}
public string ResponseText { get; set; }
public WebExceptionStatus Status { get; set; }
}
also don't forget to add the https://oauth.googlecode.com/svn/code/csharp/OAuthBase.cs to the project
it's ready to use. to read from api :
var request = CreateAuthorizedRequest(MagentoServer + "/api/rest/products", "get", new ApiFilter() {Page = 1 });
var responseText = FetchRequest(request);
Magento REST Api documantion can be found here
you can quickly create a client REST API using Spring.NET Social :
http://www.springframework.net/social/
Magento uses OAuth 1.0a authentication like Twitter. You can take a look to the Twitter implementation here:
http://www.springframework.net/social-twitter/
And the related documentation with step by step instructions:
http://www.springframework.net/social/refdoc/implementing.html
I'm not sure if this helps or not, but once I was able to get the oauth_token and oauth_token_secret from Magento (I used a PHP Magento sample to get it) I was able to query the REST API by putting everything in your requestUri into the header.
Your example helped me get most of the code correct, and just modified it a little (here's a little snippet):
StringBuilder sb = new StringBuilder("OAuth ");
sb.AppendFormat("oauth_version={0},", "1.0");
sb.AppendFormat("oauth_signature_method={0},", "HMAC-SHA1");
sb.AppendFormat("oauth_nonce={0},", nonce);
sb.AppendFormat("oauth_timestamp={0},", timeStamp);
sb.AppendFormat("oauth_consumer_key={0},", consumerKey);
sb.AppendFormat("oauth_token={0},", oauth_token);
sb.AppendFormat("oauth_signature={0}", sig);
Debug.WriteLine(sb.ToString());
var request = (HttpWebRequest)WebRequest.Create((resourceUrl));
request.Headers[HttpRequestHeader.Authorization] = sb.ToString();
request.ContentType = "text/xml";
request.Accept = "text/xml";
request.KeepAlive = true;
//request.Method = WebRequestMethods.Http.Get;
request.Method = "GET";
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
Debug.WriteLine(response.StatusCode);
Debug.WriteLine(response.Server);
if (response.StatusCode == HttpStatusCode.OK)
{
Stream responseStream = response.GetResponseStream();
StreamReader responseReader = new StreamReader(responseStream);
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(response.GetResponseStream());
Dts.Variables["User::XML_Response"].Value = xmlDoc.OuterXml.ToString();
}
Does that help?

Categories