I am trying to find out how to update data in Dynamics CRM and I fail miserably.
private const string Url = "*****/XRMServices/2011/OrganizationData.svc/";
private const string userName = "username";
private const string password = "password";
private readonly HttpClientHandler _handler;
NetworkCredential credentials = new NetworkCredential(userName, password);
_handler = new HttpClientHandler { Credentials = credentials };
public void Put()
{
StringContent content = new StringContent("<feed><entry><content><m:properties><d:Address1_Country>NEW VALUE</d:Address1_Country></m:properties></content></entry></feed>");
using (HttpClient client = new HttpClient(_handler))
{
client.PutAsync(Url + "AccountSet(guid'182df667-c4f6-e111-8042-0050568e0828')", content).Result;
}
}
The response I get is:
response = {StatusCode: 415, ReasonPhrase: 'Unsupported Media Type', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
{
DataServiceVersion: 1.0;
Persistent-Auth: true
Cache-Control: private
Date: Tue, 10 Mar 2015 10:22:07 GMT
Server: Micr...
You are trying to use OData endpoint that would not work outside of CRM webresources. Try to use SOAP endpoint for your purpose:
https://msdn.microsoft.com/en-us/library/gg334754.aspx
https://msdn.microsoft.com/en-us/library/gg328416.aspx
Related
I have sample code written in C# in Visual Studio on Windows 10 that attempts to send a POST request with custom headers to a service running at http://localhost:9998 which is failing.
When I look at the request the Content-Type header field is being sent as ContentType (no hyphen).
httpRequestMessage:Method: POST, RequestUri: 'http://localhost:9998/',
Version: 1.1, Content: System.Net.Http.ByteArrayContent, Headers: {
ContentType: application/vnd.com.documents4j.any-msword Accept:
application/pdf Converter-Job-Priority: 1000 }response:StatusCode:
500, ReasonPhrase: 'Request failed.', Version: 1.1, Content:
System.Net.Http.StreamContent, Headers: { Connection: close Date:
Sat, 10 Apr 2021 22:39:24 GMT Content-Length: 1031 Content-Type:
text/html; charset=ISO-8859-1 }Press any key to continue . . .
I am wondering if this is the cause of the problem?
I have code written in C# that uses RestSharp and that sends Content-Type correctly and returns a successful result.
I have code written in Java that also sends Content-Type correctly and returns a successful result.
Sample Code 1 [Problem sending Content-Type as ContentType]
using System;
using System.Net;
using System.IO;
using System.Net.Http;
namespace HttpPOST10
{
class Program
{
public static string MyUri { get; private set; }
static void Main(string[] args)
{
// string url = "http://localhost:9998";
string url = "http://localhost:8888"; // Fiddler
Uri myUri = new Uri(url);
string srcFilename = #"C:\temp2\Sample.doc";
string destFileName = #"C:\temp3\Sample-HttpPOST10.pdf";
UploadFile(url, srcFilename, destFileName);
}
private static bool UploadFile(string url, string srcFilename, string destFileName)
{
HttpClient httpClient = new HttpClient();
byte[] data;
data = File.ReadAllBytes(srcFilename);
var httpRequestMessage = new HttpRequestMessage
{
Method = HttpMethod.Post,
RequestUri = new Uri(url),
Headers = {
{ HttpRequestHeader.ContentType.ToString(), "application/vnd.com.documents4j.any-msword" },
{ HttpRequestHeader.Accept.ToString(), "application/pdf" },
{ "Converter-Job-Priority", "1000" },
// {"User-Agent", "RestSharp/106.11.8.0" }
},
Content = new ByteArrayContent(data)
};
Console.Write("httpRequestMessage:" + httpRequestMessage);
var response = httpClient.SendAsync(httpRequestMessage).Result;
Console.Write("response:" + response);
return true;
}
}
}
Thank you Jimi - have now got a successful response.
httpRequestMessage:Method: POST, RequestUri: 'http://localhost:9998/',
Version: 1.1, Content: System.Net.Http.ByteArrayContent, Headers: {
ContentType: application/vnd.com.documents4j.any-msword Accept:
application/pdf Converter-Job-Priority: 1000 Content-Type:
application/vnd.com.documents4j.any-msword }response:StatusCode: 200,
ReasonPhrase: 'OK', Version: 1.1, Content:
System.Net.Http.StreamContent, Headers: { Vary: Accept-Encoding
Transfer-Encoding: chunked Date: Mon, 12 Apr 2021 03:04:14 GMT
Content-Type: application/pdf
The code change was:
private static bool UploadFile(string url, string srcFilename, string destFileName)
{
HttpClient httpClient = new HttpClient();
byte[] data;
data = File.ReadAllBytes(srcFilename);
HttpContent content = new ByteArrayContent(data);
content.Headers.Add("Content-Type", "application/vnd.com.documents4j.any-msword");
var httpRequestMessage = new HttpRequestMessage
{
Method = HttpMethod.Post,
RequestUri = new Uri(url),
Headers = {
{ HttpRequestHeader.ContentType.ToString(), "application/vnd.com.documents4j.any-msword" },
{ HttpRequestHeader.Accept.ToString(), "application/pdf" },
{ "Converter-Job-Priority", "1000" },
},
Content = content
};
Console.Write("httpRequestMessage:" + httpRequestMessage);
var response = httpClient.SendAsync(httpRequestMessage).Result;
Console.Write("response:" + response);
return true;
}
I need to get this service from c # https://learn.microsoft.com/en-us/rest/api/power-bi-embedded/capacities/resume.
For this I use the GetAccessToken () function to obtain the authentication token.
public string GetAccessToken()
{
try
{
string tenantId = "ae4e3a81-xxxxxxxxxxxxxxxxxx";
string clientId = "ca8393b2-xxxxxxxxxxxxxxxxxxxxxxxxx";
string clientSecret = "xxxxxxxxxxxxxxxxxxxxxxxxxx";
string authContextURL = "https://login.windows.net/" + tenantId;
var authenticationContext = new AuthenticationContext(authContextURL);
var credential = new ClientCredential(clientId: clientId, clientSecret: clientSecret);
var result = authenticationContext.AcquireTokenAsync(resource: "https://management.azure.com/", clientCredential: credential).Result;
if (result == null)
{
throw new InvalidOperationException("Failed to obtain the JWT token");
}
string token = result.AccessToken.ToString();
return token;
}
catch (Exception ex)
{
return ex.ToString();
}
}
Then I use the DoWork () method to use the token and be able to consume the azure ulr.
public void DoWork()
{
string Subscription = "afdbf38c-c33c-45ea-8e9b-===========";
string token = GetAccessToken();
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + token);
client.BaseAddress = new Uri("https://management.azure.com/");
// Now you can party with your HttpClient!
using (var response = client.PostAsync($"/subscriptions/{Subscription}/resourceGroups/Reportes/providers/Microsoft.PowerBIDedicated/capacities/powerbiembeddedjre1/resume?api-version=2017-10-01", null).Result)
{
response.EnsureSuccessStatusCode();
}
}
}
But when I go to check the response it generates an error message:
{StatusCode: 403, ReasonPhrase: 'Forbidden', Version: 1.1, Content:
System.Net.Http.StreamContent, Headers: {Pragma: no-cache
x-ms-failure-cause: gateway x-ms-request-id:
02d9df62-0529-4a7f-b492-36ce8584aad6 x-ms-correlation-request-id:
02d9df62-0529-4a7f-b492-36ce8584aad6 x-ms-routing-request-id:
CANADACENTRAL: 20191114T163756Z: 02d9df62-052949-7 36ce8584aad6
Strict-Transport-Security: max-age = 31536000; includeSubDomains
X-Content-Type-Options: nosniff Connection: close Cache-Control:
no-cache Date: Thu, 14 Nov 2019 16:37:55 GMT Content-Length: 503
Content-Type: application / json; charset = utf-8 Expires: -1}}
What do I need to solve this problem?
looks like an issue with the bearer token, try client.SetBearerToken(token);
alternatively it's correctly sending back 403 because you do not meet the requirements for the claims (tenet/client issue).
I'm trying to get the data from the website programatically using c# httpclient, but i'm unable to fetch the data.
I have provided the link below
https://ngodarpan.gov.in/index.php/home/statewise_ngo/5972/33/1
there will be a list of data shown in the table format, if you click on the any of the link there will be a popup with a full set of details, which i require to get it programatically for each record.
I have tried generating the csrf_token everytime by hitting the below link
https://ngodarpan.gov.in/index.php/ajaxcontroller/get_csrf
and try to pass the csrf token & id to the following link
https://ngodarpan.gov.in/index.php/ajaxcontroller/show_ngo_info
but this throws an error 403 forbidden.
private void sample1()
{
string str =
"https://ngodarpan.gov.in/index.php/ajaxcontroller/show_ngo_info";
var client = new HttpClient();
var pairs = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("id", "169486"),
new KeyValuePair<string, string>("csrf_cookie_name",
"decab99c17a84a9040a03c362317289c")
};
var content = new FormUrlEncodedContent(pairs);
var response = client.PostAsync(str, content).Result;
}
{StatusCode: 403, ReasonPhrase: 'Forbidden', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
{
Date: Sun, 09 Jun 2019 07:01:09 GMT
Set-Cookie: csrf_cookie_name=2e39ed6c9bb142836d81233ba1a94732; expires=Sun, 09-Jun-2019 07:01:11 GMT; Max-Age=2; path=/; httponly
Server: Apache/2.4.6
Server: (Red Hat Enterprise Linux)
Server: OpenSSL/1.0.1e-fips
Server: mod_fcgid/2.3.9
Server: PHP/5.6.30
Server: mod_wsgi/3.4
Server: Python/2.7.5
X-Powered-By: PHP/5.6.30
Content-Length: 1131
Content-Type: text/html; charset=UTF-8
}}
when you get csrf_token you should set its value to two things. csrf_test_name in request body and csrf_cookie_name in cookies. you can see network tab details in browser for more details.
private async Task sample1()
{
var url = "https://ngodarpan.gov.in";
var uri = new Uri(url);
string str = $"{url}/index.php/ajaxcontroller/show_ngo_info";
var csrf_token = "80c719c60ac281c34f2f7720fbd28be9";
HttpClientHandler handler = new HttpClientHandler();
handler.CookieContainer = new CookieContainer();
handler.CookieContainer.Add(uri, new Cookie("csrf_cookie_name",csrf_token)); // Adding a Cookie
var client = new HttpClient(handler);
client.DefaultRequestHeaders.Add("X-Requested-With", "XMLHttpRequest");
var pairs = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("id", "169486"),
new KeyValuePair<string, string>("csrf_test_name", csrf_token)
};
var content = new FormUrlEncodedContent(pairs);
var response = await client.PostAsync(str, content);
using (FileStream fS = File.Create("result.json"))
{
await response.Content.CopyToAsync(fS);
}
Console.WriteLine(response);
}
I am doing a POC on sending data to Azure event hub using C#. The data will be posted over http unlike the Eventhub client. As per the requirements I cam creating a SAStoken to be embedded in http header. However when posting I get 501, Unauthorized access error. Not sure where I am going wrong. Here is the code that I have written
public static async Task<HttpResponseMessage> SendDataUsingHttp()
{
// Namespace info.
var serviceNamespace = "myeventhubs";
var hubName = "eventhub1";
var url = string.Format("{0}/publishers/{1}/messages", hubName, 1);
//var url = string.Format("{0}/messages", hubName);
var baseUri = new
Uri(string.Format("https://{0}.servicebus.windows.net/"
, serviceNamespace));
var SharedAccessKeyName = "All";
var SharedAccessKey = "<shared access key>";
var sasToken =
createSasToken(baseUri.ToString(),SharedAccessKeyName,
SharedAccessKey);
var evtData = new
{
Temperature = new Random().Next(20, 50)
};
var payload = JsonConvert.SerializeObject(evtData);
// Create client.
var httpClient = new HttpClient
{
BaseAddress = baseUri
};
httpClient.DefaultRequestHeaders.Accept.Clear();
httpClient.DefaultRequestHeaders.Authorization = new
System.Net.Http.Headers.AuthenticationHeaderValue
("SharedAccessSignature", sasToken);
var content = new StringContent(payload, Encoding.UTF8);
content.Headers.ContentType = new
System.Net.Http.Headers.MediaTypeHeaderValue("application/json");
HttpResponseMessage result = null;
try
{
result = await httpClient.PostAsync(url, content);
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
return result;
}
private static string createSasToken(string baseUri, string keyName,
string key)
{
TimeSpan sinceEpoch = DateTime.UtcNow - new DateTime(1970, 1, 1);
var week = 60 * 60 * 24 * 7;
var expiration = Convert.ToString((int)sinceEpoch.TotalSeconds +
week);
string stringToSign = HttpUtility.UrlEncode(baseUri) + "\n" +
expiration;
HMACSHA256 hmac = new HMACSHA256(Encoding.UTF8.GetBytes(key)); //--
var signature =
Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(
stringToSign)));
var sasToken = String.Format(CultureInfo.InvariantCulture,
"SharedAccessSignature sr={0}&sig={1}&se={2}&skn={3}",
HttpUtility.UrlEncode(baseUri), HttpUtility.UrlEncode(signature),
expiration, keyName);
return sasToken;
}
result
{StatusCode: 401, ReasonPhrase: 'Unauthorized', Version: 1.1,
Content: System.Net.Http.StreamContent, Headers: {
Transfer-Encoding: chunked Strict- Transport-Security:
max-age=31536000 Date: Sun, 17 Jun 2018 08:35:43 GMT Server:
Microsoft-HTTPAPI/2.0 Content-Type: application/xml; charset=utf-8
}} Content: {System.Net.Http.StreamContent} Headers:
{Transfer-Encoding: chunked Strict-Transport-Security:
max-age=31536000 Date: Sun, 17 Jun 2018 08:35:43 GMT Server:
Microsoft-HTTPAPI/2.0
Based on your createSasToken method, it would generate the authorization header value with the following format:
Authorization: SharedAccessSignature sr={0}&sig={1}&se={2}&skn={3}
For your request, you also specify the following code:
System.Net.Http.Headers.AuthenticationHeaderValue("SharedAccessSignature", sasToken);
Using Fiddler to capture the network traces, you would find that your authorization header value in your sent request would look like this:
Authorization: SharedAccessSignature SharedAccessSignature sr={0}&sig={1}&se={2}&skn={3}
For your code, you need to adjust the format of your sasToken under the createSasToken method.
Moreover, the baseUri parameter of createSasToken method needs to be the full request path you are requesting. So you need to modify the related code under SendDataUsingHttp for generating the token as follows:
var sasToken =createSasToken(baseUri+url, SharedAccessKeyName, SharedAccessKey);
I am trying to call the OpenPaths.cc rest service API which requires 2-legged OAuth. For this I use the DevDefined.OAuth library (I tried the nuget package and the latest from github). It works when I don't pass parameters in the querystring but returns 400 NOT AUTHORIZED when I do pass parameters.
Working sample with no parameters:
public class OpenPathsRequest
{
private const string accessKey = "your personal access key";
private const string secretKey = "your personal secret";
private const string url = "https://openpaths.cc/api/1";
private OAuthSession session;
public OpenPathsRequest()
{
var consumerContext = new OAuthConsumerContext
{
ConsumerKey = accessKey,
ConsumerSecret = secretKey,
SignatureMethod = SignatureMethod.HmacSha1,
UseHeaderForOAuthParameters = true
};
session = new OAuthSession(consumerContext, url, url, url);
}
private string GetWebResponseAsString(HttpWebResponse response)
{
Encoding enc = System.Text.Encoding.GetEncoding(1252);
StreamReader loResponseStream = new StreamReader(response.GetResponseStream(), enc);
return loResponseStream.ReadToEnd();
}
public string GetResponse()
{
HttpWebResponse response = session.Request().Get().ForUrl(url).ToWebResponse();
var result = GetWebResponseAsString(response);
return result;
}
}
class Program
{
static void Main(string[] args)
{
// create new OpenPathsRequest and get result
var request = new OpenPathsRequest();
var response = request.GetResponse();
Console.WriteLine(response);
Console.WriteLine("Press any key...");
Console.ReadKey();
}
}
But when I change the GetResponse method and pass in 2 parameters (start_time and end_time) like so:
public string GetResponse()
{
HttpWebResponse response = session.Request().Get().ForUrl(url).WithQueryParameters(
new { start_time = 1364962612, end_time = 1364991412 }).ToWebResponse();
var result = GetWebResponseAsString(response);
return result;
}
Which results in the following HTTP request (consumer key omitted):
GET https://openpaths.cc/api/1?start_time=1364962612&end_time=1364991412 HTTP/1.1
Authorization: OAuth oauth_nonce="7b5da37a-6227-4ded-ae8b-a695e789ef90",oauth_consumer_key="**********",oauth_signature_method="HMAC-SHA1",oauth_timestamp="1365058952",oauth_version="1.0",oauth_signature="tAk4KMj%2FsiG6BTLSmvDNKXbBpNs%3D"
Host: openpaths.cc
Connection: Keep-Alive
I get the an error response:
HTTP/1.1 400 Bad Request
Date: Thu, 04 Apr 2013 07:03:26 GMT
Content-Type: text/html; charset=UTF-8
Connection: keep-alive
Content-Length: 19
Server: TornadoServer/2.0
Set-Cookie: _xsrf=bf20487382b64eeb8646d31b0770db85; Path=/
Set-Cookie: session_id=ZTk2Mjk1MzIzNWNiMmRjMTY1ZmY5Y2ExNWUwMGY5ZTAxZmY1NGIyODljZGJiNzRlMmIyMWI4NTA3YzUwYWJlYg==|1365059006|7459a7ff95039279e9686ceb76b58918fd9f3e48; expires=Thu, 04 Apr 2013 07:18:26 GMT; Path=/
400: NOT AUTHORIZED
All help would be appreciated very much. Thanks in advance.
Harmen
Solved! Apparently OpenPaths.cc api requires signing WITHOUT the additional query parameters in the signature base string. I believe this is not according to OAuth specs, is it? Anyway, with DevDefined.OAuth i can easily solve this by calling SignWithoutToken before calling WithQueryParameters like so:
public string GetResponse()
{
HttpWebResponse response = session.Request().Get().ForUrl(url).
SignWithoutToken().
WithQueryParameters(new { start_time = 1364962612, end_time = 1364991412 }).
ToWebResponse();
var result = GetWebResponseAsString(response);
return result;
}