web client PUT method in MVC - c#

I am trying to do PUT method for API service
Here is the code:
WebClient box = new WebClient();
var uuid = "40922d72-57dd-4fa6-bd64-f406f444dbb6";
if (HttpContext.Current.Session["JSESSIONCOOKIE"] != null)
{
}
else
{
return null;
}
box.Headers["Cookie"] = HttpContext.Current.Session["JSESSIONCOOKIE"].ToString();
string sampleJson = "{" + "autoPresetTimes" + ":" + "{" + "0" + ":" + "Night" + "}}".ToString();
string json = new JavaScriptSerializer().Serialize(sampleJson);
Uri uri = new Uri("https://my.zipato.com:443/zipato-web/v2/thermostats/" + uuid + "/config");
box.UploadString(uri, "PUT", json);
My problem is that this above gives me error 500 from server. I think because i dont send my body like this:
{"autoPresetTimes": {
"0": "Night"
}
}
On API page it says Parameter content type: application/json so i guess i should send my response o look like this above.
Any thoughts on this?

The json that you are creating looks incorrect. You need to put your keys within double quotes.
string json =
"{" + "\"autoPresetTimes\"" + ":" + "{" + "\"0\"" + ":" + "\"Night\"" + "}}";
Uri uri =
new Uri("https://my.zipato.com:443/zipato-web/v2/thermostats/" + uuid + "/config");
box.UploadString(uri, "PUT", json);
Note: You do not need to specify port 443 in your url. The default port for https is 443

Related

Calling ashx service returns 500 internal server error even though service completes the business

I am calling ashx service for creating users on third party, I have URL and query string parameters set. the request accepts POST/GET http methods, and the response should return response code and response text as xml.
The weird thing is the users are being created but the response throws an exception [500 Internal Server error].
Here is the Code:
string URI = "https://thirdpartyservice.com/ApiHandler.ashx?";
string params = "ptf_cmd=403&ptf_method=md5" +
"&ptf_timer=" + sTimer +
"&ptf_check=" + sCheck +
"&ptf_client=" + rsaClient +
"&ptf_partner=" + sPartner +
"&ptf_offername=" + offername +
"&ptf_host=" + rsaHost +
"&ptf_login=" + sLogin +
"&ptf_password=" + password +
"&ptf_firstname=" + firstName +
"&ptf_lastname=" + lastName +
"&ptf_email=" + userEmail +
"&ptf_interfacelanguage=" + rsaInterfaceLanguage +
"&ptf_role=" + rsaUserRole +
"&ptf_pupildiscipline=" + rsaPupilDiscipline +
"&ptf_detailedResult=1" +
"&ptf_endingurl=" + rsaReturnUrl +
"&ptf_admingroup=" + rsaAdminGroup +
"&ptf_pedagroup=" + rsaPedaGroup +
"&ptf_usercreationmode=API";
using (var wc = new WebClient())
{
wc.Headers[HttpRequestHeader.ContentType] = "application/x-www-form-urlencoded";
string xmlResult = wc.DownloadString(URI + params); //throws exception [500 Internal Server Error].
//string xmlResult = wc.UploadString(URI, params);//throws exception [500 Internal Server Error].
}
I tried the request without setting the header and both POST/GET but also throws an exception.
Also I used HttpWebRequest class to send the request but it fails. Any suggestion(s) how to handle this?

How to send a POST in UWP c#

I need to send a POST method but it says invalid JSON content, do somebody knows what im doing wrong in the JSON format ¿?, ill apreciate a lot.
Uri resourceAddress;
if (!Helpers.TryGetUri(pcHost + pcPort + "/api/code/scan", out resourceAddress))
{
rootPage.NotifyUser("Invalid URI.", NotifyType.ErrorMessage);
return;
}
try
{
terminalRef = "1";
//code = "Uc0E17G4nW";
IHttpContent jsonContent = new HttpJsonContent(JsonValue.Parse("{\"code\":\"" + code +
",\"ref\" : \""+ terminalRef +
"\"}"));
HttpResponseMessage response = await httpClient.PostAsync(resourceAddress, jsonContent).AsTask(cts.Token);
Debug.WriteLine(".");
//await Helpers.DisplayTextResultAsync(response, cts.Token);
rootPage.NotifyUser("Completed", NotifyType.StatusMessage);
}
catch (Exception ex)
{
rootPage.NotifyUser("Error: " + ex.Message, NotifyType.ErrorMessage);
String errorMessage = ex.Message.ToString();
}
Noted that your string is not correctly formatted. Can you try the parsing below string,
"{\"code\" : \"" + code + "\", \"ref\" : \"" + terminalRef + "\"}"
The first way was as the Jaliya Udagedara's suggestion, you would need to check your json string's format to make sure that it's correct.
Another a simple way is using the Newtownsoft.Json to convert a c# object.
For example:
string jsonstring = JsonConvert.SerializeObject(new {code="code", Ref = "terminalRef" });
IHttpContent jsonContent = new HttpStringContent(jsonstring, Windows.Storage.Streams.UnicodeEncoding.Utf8, "application/json");
HttpResponseMessage response = await httpClient.PostAsync(resourceAddress, jsonContent).AsTask(cts.Token);
After multiple failures i found how to make it works ( at least for me) hope it can help people working with Windows 10 iot in Universal Windows Platform (UWP) i know how difficult can be to fin proper documentation.
Uri resourceAddress;
if (!Helpers.TryGetUri(Host + Port + "/XXX/YYY/directory", out resourceAddress))
{
return;
}
IHttpContent jsonContentCoordinates = new HttpJsonContent(JsonValue.Parse("{\"zzz\": \"" + something
+ "\", \"xxx\": \"" + somethingXXX
+ "\",\"yyy\": \"" + somethingYYY
+ "\" }"));
HttpResponseMessage httpResponseCoordinates = new HttpResponseMessage();
string httpResponseBodyCoordinates = "";
try
{
httpResponseCoordinates = await httpClient.PostAsync(resourceAddress, jsonContentCoordinates).AsTask(cts.Token);
httpResponseBodyCoordinates = await httpResponseCoordinates.Content.ReadAsStringAsync();
httpResponseCoordinates.EnsureSuccessStatusCode();
FlagInternetNotConnected = false;
}
catch (Exception)
{
//Catch it if it fails.
}

How to download a private bitbucket.org repository using pure REST API calls, version 1 or 2

I'm trying to clone/download my private bitbucket.org repository using C#, but I want to do it using pure HTTPS REST calls, and not a third party lib, i want to learn how it works.
So far I could only find example code for version 1 of the api.
This is what i've got working so far in C#:
static void AUthenticate()
{
var time = GenerateTimeStamp();
var url = "https://bitbucket.org/api/1.0/oauth/request_token";
var secret = "SECRET";
var key = "KEY";
var sigBaseStringParams = "";
sigBaseStringParams += "oauth_callback=http%3A%2F%2Flocal%3Fdump";
sigBaseStringParams += "&" + "oauth_consumer_key=" + key;
sigBaseStringParams += "&" + "oauth_nonce=" + GetNonce();
sigBaseStringParams += "&" + "oauth_signature_method=" + "HMAC-SHA1";
sigBaseStringParams += "&" + "oauth_timestamp=" + time;
sigBaseStringParams += "&" + "oauth_version=1.0";
var sigBaseString = "POST&";
sigBaseString += Uri.EscapeDataString(url) + "&" + Uri.EscapeDataString(sigBaseStringParams);
var signature = GetSignature(sigBaseString, secret);
var res = PostData(url, sigBaseStringParams + "&oauth_signature=" + Uri.EscapeDataString(signature));
var items = GetParameters(res);
var tokenSecret = items["oauth_token_secret"];
var token = items["oauth_token"];
var callbackConfirmed = items["oauth_callback_confirmed"];
url = "https://bitbucket.org/api/1.0/oauth/authenticate?oauth_token=" + token;
}
This authenticates and I get 3 values back. The last URL i paste into a browser, where i grant my application access and i end up with an oauth_verifier
Note: I don't really want to do this as I am writing a server program which won't really be able to send a user to a browser link (but one thing at a time)
I then run the following code:
var url = "https://bitbucket.org/api/1.0/oauth/access_token";
var token = "TOKEN FROM PREV CALL";
var time = GenerateTimeStamp();
var sigBaseStringParams = "";
//sigBaseStringParams += "oauth_callback=http%3A%2F%2Flocal%3Fdump";
var secret = "SECRET";
var key = "KEY";
sigBaseStringParams += "oauth_consumer_key=" + key;
sigBaseStringParams += "&" + "oauth_token=" + token;
sigBaseStringParams += "&" + "oauth_nonce=" + GetNonce();
sigBaseStringParams += "&" + "oauth_signature_method=" + "HMAC-SHA1";
sigBaseStringParams += "&" + "oauth_timestamp=" + time;
sigBaseStringParams += "&" + "oauth_verifier=AUTH VERIFIER FROM PREV CALL";
var sigBaseString = "POST&";
sigBaseString += Uri.EscapeDataString(url) + "&" + Uri.EscapeDataString(sigBaseStringParams);
var tokenSecret = "TOKEN SECRET FROM PREVIOUS CALL";
var signature = GetSignature(sigBaseString, secret, tokenSecret);
var res = PostData(url, sigBaseStringParams + "&oauth_signature=" + Uri.EscapeDataString(signature));
This gives me a 400 bad request. I can't see much else.
I'm following the steps on this page: https://confluence.atlassian.com/bitbucket/oauth-on-bitbucket-cloud-238027431.html#OAuthonBitbucketCloud-Refreshtokens
Why I'm doing this is because i want to eventually make a POST request (or GET) to this URL:
var url2 = "https://bitbucket.org/ACCOUNT/REPOSITORY/get/tip.zip?access_token="+token;
Because I think this will give me the entire repository in a zip file. If i put this in the browser it works because i'm logged into bitbucket.
If there is a newer/easier/better way i'm open to suggestions.
Thanks in advance
I found a very simple solution.
I just had to provide credentials to a GET request:
public static void Downloadfiles(string username, string password, string account, string repository, string pathToSave)
{
var creds = Base64Encode(String.Format("{0}:{1}", username, password));
var url = String.Format("https://bitbucket.org/{0}/{1}/get/tip.zip", account, repository);
using (var client = new WebClient())
{
client.Headers.Add("Authorization", "Basic " + creds);
client.Headers.Add("Content-Type", "application/octet-stream");
client.DownloadFile(url, pathToSave);
}
}

How to generate the Azure Table Service SAS token from c# code?

I would like to generate the SAS token for Azure table service from C# code. I generated the one from the portal which looks like
?sv=2016-05-31&ss=t&srt=sco&sp=rwdlacu&se=2017-03-23T20:05:14Z&st=2017-03-23T12:05:14Z&sip={MY_IP}&spr=https&sig=fL9GNAZqybSlQKWvaspwr%2FrFFtWO%2F5jVgFu1Ayu94Ic%3D
How to generate such kind of token from c# code? If there is any tutorial please redirect me to it.
I tried with a method below, but the token generated is invalid.
UPDATED CODE
I am still getting an error 403 Forbidden. Is my code to compute the signature correct?
var StringToSign = "{Storage_account_name}" + "\n" +
"rwdlacu" + "\n" +
"t" + "\n" +
"sco" + "\n" +
"2017-03-24T12:05:14Z" + "\n" +
"2017-03-24T20:05:14Z" + "\n" +
"{IP}" + "\n" +
"https" + "\n" +
"2016-05-31" + "\n";
string encodedString = HttpUtility.UrlEncode(StringToSign);
HMACSHA256 hmac = new HMACSHA256(Convert.FromBase64String("accountkey"));
var signature = Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(encodedString)));
The reason you're running into the issue is because you're calculating signature for SAS based on the logic for calculating Authorization header. StringToSign is different in both cases.
For SAS, this should be (for Service SAS):
StringToSign = signedpermissions + "\n" +
signedstart + "\n" +
signedexpiry + "\n" +
canonicalizedresource + "\n" +
signedidentifier + "\n" +
signedIP + "\n" +
signedProtocol + "\n" +
signedversion + "\n" +
startingPartitionKey + "\n"
startingRowKey + "\n"
endingPartitionKey + "\n"
endingRowKey
If you want to use Account SAS (which is what Portal does), it should be:
StringToSign = accountname + "\n" +
signedpermissions + "\n" +
signedservice + "\n" +
signedresourcetype + "\n" +
signedstart + "\n" +
signedexpiry + "\n" +
signedIP + "\n" +
signedProtocol + "\n" +
signedversion + "\n"
So based on your parameters, the StringToSign for Account SAS would be:
StringToSign = {youraccountname} + "\n" +
"rwdlacu" + "\n" +
"t" + "\n" +
"sco" + "\n" +
"2017-03-23T12:05:14Z" + "\n" +
"2017-03-23T20:05:14Z" + "\n" +
{yourip} + "\n" +
"https" + "\n" +
"2016-05-31 + "\n"
The computation for signature is correct.
You may find these links helpful to learn more about computing SAS: Account SAS and Service SAS.
UPDATE
There's an issue with hmac calculation as well. It should be using your account key and also it should use Convert.FromBase64String.
HMACSHA256 hmac = new HMACSHA256(Convert.FromBase64String(accountKey));
Also, you should not URLEncode StringToSign. Elements there should be URL decoded.
Lastly the SAS token should look like what you're getting back from the portal.
Code Sample
static void AccountSasSample()
{
var accountName = "your-account-name";
var accountKey = "your-account-key";
var start = DateTime.UtcNow.AddHours(-1).ToString("yyyy-MM-ddTHH:mm:ssZ");
var end = DateTime.UtcNow.AddHours(1).ToString("yyyy-MM-ddTHH:mm:ssZ");
var permission = "rwdlacu";
var serviceType = "t";
var resourceTypes = "sco";
var ipAddress = "your-ip-address";
var protocol = "https";
var serviceVersion = "2016-05-31";
var stringToSign = string.Format("{0}\n{1}\n{2}\n{3}\n{4}\n{5}\n{6}\n{7}\n{8}\n", accountName, permission, serviceType, resourceTypes, start, end, ipAddress, protocol, serviceVersion);
Console.WriteLine(stringToSign);
HMACSHA256 hmac = new HMACSHA256(Convert.FromBase64String(accountKey));
string signature = Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(stringToSign)));
var sasToken = string.Format("?sv={0}&ss={1}&srt={2}&sp={3}&se={4}&st={5}&sip={6}&spr={7}&sig={8}", serviceVersion,
serviceType, resourceTypes, permission, end, start, ipAddress, protocol, HttpUtility.UrlEncode(signature));
Console.WriteLine(sasToken);
var urlToListTables = string.Format("https://{0}.table.core.windows.net/Tables{1}", accountName, sasToken);
//Copy this urlToListTables & paste it in browser's address bar. You should be able to see the list of tables in your storage account.
}
//account name
var storageAccountName = ConfigProvider.AccountName;
// your storage account access key here
var accessKey = ConfigProvider.BlobKey;
// connect to our storage account and create a blob client
var connectionString = String.Format("DefaultEndpointsProtocol=https;AccountName={0};AccountKey={1}",
storageAccountName,
accessKey);
var storageAccount = CloudStorageAccount.Parse(connectionString);
var blobClient = storageAccount.CreateCloudBlobClient();
SharedAccessAccountPolicy policy = new SharedAccessAccountPolicy()
{
Permissions = SharedAccessAccountPermissions.Write | SharedAccessAccountPermissions.Create,
Services = SharedAccessAccountServices.Blob,
ResourceTypes = SharedAccessAccountResourceTypes.Container | SharedAccessAccountResourceTypes.Object,
SharedAccessExpiryTime = DateTime.UtcNow.AddMonths(1),
Protocols = SharedAccessProtocol.HttpsOnly,
};
string sasToken = storageAccount.GetSharedAccessSignature(policy);
Why not use Azure Storage Client Library to generate SAS? You can refer to: https://learn.microsoft.com/en-us/azure/storage/storage-dotnet-shared-access-signature-part-1

How to retrieve an annotation in web resource and display it using popup window - crm 2011

How to show annotation present in an entity in popup window by using html web resource. My requirement is to display annotation present in an entity in a popup window and in popup window user should be able to delete , upload and convert the annotation to pdf (if he wants). Can you suggest a best method to achieve this in crm 2011.
function retann() {
//debugger;
var serverUrl = Xrm.Page.context.getServerUrl();
var GUIDvalue = Xrm.Page.data.entity.getId();
// Creating the Odata Endpoint
var oDataPath = "http://url/organization/XRMServices/2011/OrganizationData.svc/";
var retrieveReq = new XMLHttpRequest();
var Odata = oDataPath + "/AnnotationSet?$select=DocumentBody,FileName,MimeType,ObjectId&$filter=ObjectId/Id eq guid'" + GUIDvalue + "'";
retrieveReq.open("GET", Odata, false);
retrieveReq.setRequestHeader("Accept", "application/json");
retrieveReq.setRequestHeader("Content-Type", "application/json; charset=utf-8");
retrieveReq.onreadystatechange = function () { retrieveReqCallBack(this); };
retrieveReq.send();
}
function retrieveReqCallBack(retrieveReq) {
if (retrieveReq.readyState == 4 /* complete */) {
//debugger;
var retrieved = this.parent.JSON.parse(retrieveReq.responseText).d;
var message = "";
var fun_var =
"<script type=text/javascript>" +
"function result_value()" +
"{" +
"var rad_val;" +
"for (var i=0; i < document.orderform.test.length; ++i){if (document.orderform.test[i].checked){rad_val = document.orderform.test[i].value;}}" +
"if(rad_val==null || rad_val=='')" +
"{" +
"window.top.opener.Xrm.Page.data.entity.attributes.get('new_radiovalue').setValue('0');" +
"}" +
"else" +
"{" +
"window.top.opener.Xrm.Page.data.entity.attributes.get('new_radiovalue').setValue(rad_val);" +
"}" +
" window.top.opener.Xrm.Page.data.entity.attributes.get('new_fireplugin').setValue(1);" +
"window.top.opener.Xrm.Page.data.entity.save();" +
"this.window.close();" +
"}" +
"function result_value1()" +
"{" +
"var rad_val1;" +
"for (var i=0; i < document.orderform.test.length; ++i){if (document.orderform.test[i].checked){rad_val1 = document.orderform.test[i].value;}}" +
"if(rad_val1==null || rad_val1=='')" +
"{" +
"window.top.opener.Xrm.Page.data.entity.attributes.get('new_radiovalue').setValue('0');" +
"}" +
"else" +
"{" +
"window.top.opener.Xrm.Page.data.entity.attributes.get('new_radiovalue').setValue(rad_val1);" +
"}" +
" window.top.opener.Xrm.Page.data.entity.attributes.get('new_delete').setValue(1);" +
"window.top.opener.Xrm.Page.data.entity.save();" +
"this.window.close();" +
"}" +
"</script>";
var n = retrieved.results.length;
for (var i = 0; i < retrieved.results.length; i++) {
message += " <input type='radio' name='test' value=' " + i + "' />" + retrieved.results[i].FileName + "<br />";
}
myWindow = window.open('', '', 'width=500,height=150,left=250,top=250,scrollbars=yes,resizable=yes,directories=yes');
myWindow.document.write(fun_var + "<body bgcolor=GhostWhite style='font-family:verdana;font-size:11px;'><form name='orderform' style='font-family:verdana;font-size:11px;'>" + message + "</br><center ><input type='button' onclick='result_value()' style='font-family:verdana;font-size:11px;' value='Convert To PDF'/></center>" + "</form>");
myWindow.focus();
}
}
function SetField() {
var AddressType = Xrm.Page.data.entity.attributes.get("new_radiovalue");
AddressType.setValue("");
}
function save_form() {
// var MainPhone = Xrm.Page.data.entity.attributes.get("new_name").getValue();
//Xrm.Page.data.entity.attributes.get("new_name").setValue(MainPhone+".");
Xrm.Page.data.entity.save();
}
retrieveReqCallBack(this) function displays the popup with annoatation. Using the above code i'm able to convert doc to pdf. Since i want to add multiple functionalities like upload , delete and convert to pdf. If annotation is present then popup should have option to upload and if annotation is present then it has to show delete and convert to pdf buttons.
I found this as solution to my question,
You'll need to create a custom web resource (html) with javascript to pull the data out of the sub-grid, parse the rows, query the crm data via REST or SOAP to see if there is an annotation, then put an icon of the 'paperclip' which'll allow users to upload attachments against that record.

Categories