I'm trying to simply upload a new blob to an Azure Storage countainer using WebClient like this :
var sas = "[a new generated sas with Read, Write, List & Delete permissions]";
var sData = "This is a test!";
var sEndPoint = "http://myaccount.blob.core.windows.net/mycontainer/MyTest.txt" + sas;
var clt = new WebClient();
var res = await clt.UploadStringTaskAsync(sEndPoint, "PUT", sData);
This is giving me a "(400) Bad Request." error. Am I doing anything wrong here?
Thanks
(By the way, I need to use REST instead of Client API since I'm in a Silverlight project)
You would need to define a request header (x-ms-blob-type) for blob type and set it's value to BlockBlob. Also for Put requests you would need to define the Content-Length request header as well. I wrote a blog post on Shared Access Signatures and performing some blob operations using that (with both REST API and Storage Client library) which you can read here: http://gauravmantri.com/2013/02/13/revisiting-windows-azure-shared-access-signature/.
and here's the code from that post on uploading blob. It uses HttpWebRequest/HttpWebResponse instead of WebClient:
static void UploadBlobWithRestAPISasPermissionOnBlobContainer(string blobContainerSasUri)
{
string blobName = "sample.txt";
string sampleContent = "This is sample text.";
int contentLength = Encoding.UTF8.GetByteCount(sampleContent);
string queryString = (new Uri(blobContainerSasUri)).Query;
string blobContainerUri = blobContainerSasUri.Substring(0, blobContainerSasUri.Length - queryString.Length);
string requestUri = string.Format(CultureInfo.InvariantCulture, "{0}/{1}{2}", blobContainerUri, blobName, queryString);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(requestUri);
request.Method = "PUT";
request.Headers.Add("x-ms-blob-type", "BlockBlob");
request.ContentLength = contentLength;
using (Stream requestStream = request.GetRequestStream())
{
requestStream.Write(Encoding.UTF8.GetBytes(sampleContent), 0, contentLength);
}
using (HttpWebResponse resp = (HttpWebResponse)request.GetResponse())
{
}
}
When testing against the blob emulator this is the code I need to get it working:
var connection = ConfigurationManager.AppSettings["AzureStorageConnectionString"];
var storageAccount = CloudStorageAccount.Parse(connection);
var client = new WebClient();
client.Headers.Add("x-ms-blob-type", "BlockBlob");
client.Headers.Add("x-ms-version", "2012-02-12");
client.UploadData(string.Format(#"{0}/$root/{1}{2}", storageAccount.BlobEndpoint, myFileName, sharedAccessSignature), "PUT", _content);
Related
I want to update an already existing wiki page of tfs by using this document:
https://learn.microsoft.com/de-de/rest/api/azure/devops/wiki/pages/create%20or%20update?view=azure-devops-rest-4.1
Creating a new wiki-page (with content) is no problem. That is working fine.
But I want to edit an existing one. The tfs-documentation says that the only difference in API call is to use an "If-Match"-header (see section Request Header).
Here I have 3 situations:
Using no "If-Match"-Header or an empty: Get a "412 Precondition Failed" error.
Using a "If-Match"-Header with random value: Get a "400 Bad Request" error.
Using a "If-Match"-Header with exactly 40 characters (like the version-hash of the page-revision (e.g. '09f62be600a3b6d36d21b294dbb00921a5ba03ec')): Again "412 Precondition Failed" error.
I think the revision-hash (40 characters) should be a good way because the error message on non-40-chars returns the 400-error.
But it did not work? Has anyone an idea which id tfs is wanting? I used Postman and C# to update by API. Below you can see my example code:
var handler = new HttpClientHandler()
{
UseDefaultCredentials = true,
UseProxy = false,
};
var client = new HttpClient(handler);
client.BaseAddress = new Uri(".../pages/pagename" + "?api-version=4.1");
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
var putContent = new StringContent("{ \"content\": \"New content for page\" }", Encoding.UTF8, "application/json");
client.DefaultRequestHeaders.TryAddWithoutValidation("If-Match", "09f62be600a3b6d36d21b294dbb00921a5ba03ec");
var responseTask = client.PutAsync(client.BaseAddress, putContent);
var result = responseTask.Result;
var content = result.Content.ReadAsStringAsync().Result;
var code = result.StatusCode;
var body = content;
According to the Create or Update Wiki API, if we want to edit the wiki page,If-Match header is required. The value of If-Matchth is the wiki page ETag.
ETags can also be used for optimistic concurrency control, as a way to help prevent simultaneous updates of a resource from overwriting each other
so we need to get the wiki Etag before update. Please have a try to change the code as following:
var baseUrl = "xxxxx";
var handler = new HttpClientHandler()
{
UseDefaultCredentials = true,
UseProxy = false,
};
var client = new HttpClient(handler)
{
BaseAddress = new Uri(baseUrl)
};
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", "YourToken");
var getResult = client.GetAsync(baseUrl).Result;
var etag = getResult.Headers.GetValues("ETag");
var putContent = new StringContent("{ \"content\": \"New content for page\" }", Encoding.UTF8, "application/json");
client.DefaultRequestHeaders.TryAddWithoutValidation("If-Match", etag);
var responseTask = client.PutAsync(client.BaseAddress, putContent);
var result = responseTask.Result;
var content = result.Content.ReadAsStringAsync().Result;
Test Result:
How to make a REST call in unity3d? especially POST method. I have tried with GET request. Pls see the below get request. so i need to write POST request in Unity3d. The post rquest should be in JSON format. I tried with below code. It's hit the my service but the receiving JSON object is null. Hope your support.
var httpWebReq = WebRequest.Create("http://localhost:6091/UserService.svc/RegisterUser/") as HttpWebRequest;
httpWebReq.ContentType = "text/json;charset=utf-8";
httpWebReq.Method= "POST";
using(var streamWriter = new StreamWriter(httpWebReq.GetRequestStream()))
{
string user = "{UserID:0," +
"Email:'ruwan#gmail.com'," +
"Password:'ruwan123'," +
"NickName:'ruwa'," +
"Age:35" +
"}";
byte[] formData = UTF8Encoding.UTF8.GetBytes(user);
httpWebReq.ContentLength = formData.Length;
streamWriter.Write(formData);
}
var httpResponse = (HttpWebResponse)httpWebReq.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var responseText = streamReader.ReadToEnd();
//Now you have your response.
//or false depending on information in the response
Debug.Log(responseText);
}
use WWW for GET,
use WWW with WWWForm for POST.
Finally i got the solution thanks to all for help.
Actually the easiest way to make rest call for WCF is we have to add the Newtonsoft.Json. Finally my code is-
GET --
WebClient myWebClient = new WebClient();
myWebClient.Encoding = Encoding.UTF8;
myWebClient.Headers.Add("Content-Type", "text/json");
var json = JsonConvert.DeserializeObject<Room[] >(new WebClient().DownloadString("Your URL"));
List<yourclass> test1= new List<yourclass>();
foreach (var test in json)
{
test1.Add(new yourclass()
{
yourclass.property1 = test.property1
});
}
Debug.Log(test1);
POST---
WebClient myWebClient = new WebClient();
var Test = JsonConvert.SerializeObject(new
{
YourProperty= 0
}, new JsonSerializerSettings() { Formatting = Newtonsoft.Json.Formatting.None });
myWebClient.Encoding = Encoding.UTF8;
myWebClient.Headers.Add("Content-Type", "text/json");
string responsebody = myWebClient.UploadString("Your URL", "POST", Test );
//if(responsebody == true)
Debug.Log(responsebody);
I'm trying to work with azure storage in winrt. Since the azure storage client is not compatible with winrt I am trying to use azure's rest API. I am having a heck of a time getting the signature right and I could use another set of eyes to help me see where I'm going wrong.
Azure Account provides a name and key property, this method builds up the request right now simply listing all blobs.
'private async void BuildHTTPRequest(AzureAccount account)
{
System.Net.Http.HttpClient request = new HttpClient();
request.BaseAddress = new Uri(string.Format("http://{0}.blob.core.windows.net/", account.Name));
// Always have to use UTC date/time
request.DefaultRequestHeaders.Add("x-ms-date", DateTime.UtcNow.ToString("R", CultureInfo.InvariantCulture));
string fmtStringToSign = "{0}\n{1}\n{2}\n{3:R}\n{4}{5}";
request.DefaultRequestHeaders.Add("x-ms-version", "2011-08-18");
string hdr = CanonicalizeHeaders(request.DefaultRequestHeaders);
string authValue = string.Format(fmtStringToSign, "GET", "", "", "", hdr, "");
byte[] signatureByteForm = System.Text.Encoding.UTF8.GetBytes(authValue);
string hashKey = account.Key;
MacAlgorithmProvider macAlgorithmProvider = MacAlgorithmProvider.OpenAlgorithm("HMAC_SHA256");
BinaryStringEncoding encoding = BinaryStringEncoding.Utf8;
var messageBuffer = CryptographicBuffer.ConvertStringToBinary(authValue, encoding);
IBuffer keyBuffer = CryptographicBuffer.ConvertStringToBinary(hashKey, encoding);
CryptographicKey hmacKey = macAlgorithmProvider.CreateKey(keyBuffer);
IBuffer signedMessage = CryptographicEngine.Sign(hmacKey, messageBuffer);
string hashedString = CryptographicBuffer.EncodeToBase64String(signedMessage);
String authHeader = String.Format(CultureInfo.InvariantCulture, "{0} {1}:{2}", "SharedKey",
account.Name, hashedString);
request.DefaultRequestHeaders.Add("Authorization", authHeader);
// Send the request to the queue
try
{
var test1 = request.GetAsync("?comp=list").Result;
if (test1.IsSuccessStatusCode)
{
}
}
catch (WebException ex) { }
}
This should set the headers up for signing...
public string CanonicalizeHeaders(System.Net.Http.Headers.HttpRequestHeaders hdrCollection)
{
StringBuilder retVal = new StringBuilder();// Look for header names that start with "x-ms-" // Then sort them in case-insensitive manner.
List<string> httpStorageHeaderNameArray = new List<string>();
Dictionary<string, string> ht = new Dictionary<string, string>();
foreach (var key in hdrCollection)
{
if (key.Key.ToLowerInvariant().StartsWith("x-ms-", StringComparison.Ordinal))
{
if (ht.ContainsKey(key.Key.ToLowerInvariant()))
{
ht[key.Key.ToLowerInvariant()] = string.Format("{0},{1}", ht[key.Key.ToLowerInvariant()],
hdrCollection.FirstOrDefault(m => m.Key == key.Key).ToString().Replace("\n", string.Empty).Replace("\r", string.Empty).Trim());
}
else
{
httpStorageHeaderNameArray.Add(key.Key.ToLowerInvariant());
ht.Add(key.Key.ToLowerInvariant(),
hdrCollection.FirstOrDefault(m => m.Key == key.Key).Value.FirstOrDefault().ToString().Replace("\n", string.Empty).Replace("\r", string.Empty).Trim());
}
}
}
httpStorageHeaderNameArray.Sort();// Now go through each header's values in the sorted order and append them to the canonicalized string.
foreach (string key in httpStorageHeaderNameArray)
{
retVal.AppendFormat("{0}:{1}\n", key.Trim(), ht[key]);
}
return retVal.ToString();
}
'
Latest version of storage client library supports WinRT. You can read more about it here: http://blogs.msdn.com/b/windowsazurestorage/archive/2012/10/29/introducing-windows-azure-storage-client-library-2-0-for-net-and-windows-runtime.aspx. What I did was download the source code from Github: https://github.com/WindowsAzure/azure-sdk-for-net, opened the solution in VS 2012 and built RT project to get the necessary winmd files.
Coming to your problem, I believe you're running into this issue because you're passing an empty string for canonicalized resource string:
string authValue = string.Format(fmtStringToSign, "GET", "", "", "", hdr, "")
Please see this link for more details on creating canonicalized resource string: http://msdn.microsoft.com/en-us/library/windowsazure/dd179428.aspx.
I want to do the express checkout process in the paypal for the customers without redirecting the browser. I have written the code like
string sAPIUser = apiuser;
string sAPIPassword = password;
string sAPISignature = "signature";
string sAPIEndpoint = "https://api-3t.sandbox.paypal.com/nvp";
string sAppID = "APP-80W284485P519543T";
StringBuilder sRequest = new StringBuilder();
ASCIIEncoding encoding = new ASCIIEncoding();
string postData = ("&METHOD=SetExpressCheckout");
postData += ("&VERSION=63.0");
postData += ("&PAYMENTREQUEST_0_AMT=10.00");
postData += ("&PAYMENTREQUEST_0_CURRENCYCODE=USD");
postData += ("&PAYMENTREQUEST_0_PAYMENTACTION=Sale");
postData += ("CANCELURL=http://www.google.com");
postData += ("RETURNURL=http://www.google.com");
byte[] data = encoding.GetBytes(postData);
// Prepare web request...
HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(sAPIEndpoint);
myRequest.Method = "POST";
myRequest.Headers.Add("X-PAYPAL-SECURITY-USERID", sAPIUser);
myRequest.Headers.Add("X-PAYPAL-SECURITY-PASSWORD", sAPIPassword);
myRequest.Headers.Add("X-PAYPAL-SECURITY-SIGNATURE", sAPISignature);
myRequest.Headers.Add("X-PAYPAL-SERVICE-VERSION", "1.3.0");
myRequest.Headers.Add("X-PAYPAL-REQUEST-DATA-FORMAT", "NV");
myRequest.Headers.Add("X-PAYPAL-RESPONSE-DATA-FORMAT", "NV");
myRequest.Headers.Add("X-PAYPAL-APPLICATION-ID", sAppID);
myRequest.ContentType = "application/x-www-form-urlencoded";
myRequest.ContentLength = data.Length;
// Send the request, read the response
Stream newStream = myRequest.GetRequestStream();
newStream.Write(data, 0, data.Length);
newStream.Close();
HttpWebResponse response = (HttpWebResponse)myRequest.GetResponse();
Stream responseStream = response.GetResponseStream();
Encoding encoding2 = Encoding.GetEncoding("utf-8");
StreamReader reader = new StreamReader(responseStream, encoding2);
string theResponse = reader.ReadToEnd();
theResponse = HttpUtility.HtmlDecode(theResponse);
But i am getting the failure message in the theResponse variable. What error i am doing. The error is like
TIMESTAMP=2013%2d03%2d05T05%3a55%3a38Z&CORRELATIONID=5c10035aca937&ACK=Failure&VERSION=63%2e0&BUILD=5331358&L_ERRORCODE0=10002&L_SHORTMESSAGE0=Authentication%2fAuthorization%20Failed&L_LONGMESSAGE0=You%20do%20not%20have%20permissions%20to%20make%20this%20API%20call&L_SEVERITYCODE0=Error
How can i rectify this.
Make sure that the credentials you are using are for your sandbox account and not your live account. Your code looks like it is pointing to the sandbox, so you would need to use your sandbox credentials. Also, if this is not all of your code, make sure you are not passing across a variable called "SUBJECT" and populating it with an email address.
I'm trying to upload a photo to a REST api in a Windows Phone 7 application using RestSharp for my Gets/Posts.
The post parameters are as follows:
photo:
The photo, encoded as multipart/form-data
photo_album_id:
Identifier of an existing photo album, which may be an event or group
album
I've created my request, but every time I get back "{\"details\":\"missing photo parameter\",\"problem\":\"The API request is malformed\"}\n
My photo parameter looks like this:
"---------------------------8cd9bfbafb3ca00\r\nContent-Disposition: form-data; name=\"filename\"; filename=\"somefile.jpg\"\r\nContent-Type: image/jpg\r\n\r\n(some binary junk listed here)\r\n-----------------------------8cd9bfbafb3ca00--"
I'm not quite sure if it's a problem with how I'm presenting the binary data for the image (currently in my PhotoTaskCompleted event, I read the contents of e.ChosenPhoto into a byte[] and pass that to a helper method to create the form data) or if I just don't create the form correctly.
I'm just trying to do this a simple as possible, then I can refactor once I know how it all works.
void ImageObtained(object sender, PhotoResult e)
{
var photo = ReadToEnd(e.ChosenPhoto);
var form = PostForm(photo);
var request = new RequestWrapper("photo", Method.POST);
request.AddParameter("photo_album_id", _album.album_id);
request.AddParameter("photo", form);
request.Client.ExecuteAsync<object>(request, (response) =>
{
var s = response.Data;
});
}
private string CreateBoundary()
{
return "---------------------------" + DateTime.Now.Ticks.ToString("x");
}
private string PostForm(byte[] data)
{
string boundary = CreateBoundary();
StringBuilder post = new StringBuilder();
post.Append(boundary);
post.Append("\r\n");
post.Append("Content-Disposition: form-data; name=\"filename\"; filename=\"somefile.jpg\"");
post.Append("\r\n");
post.Append("Content-Type: image/jpg");
post.Append("\r\n\r\n");
post.Append(ConvertBytesToString(data));
post.Append("\r\n");
post.Append("--");
post.Append(boundary);
post.Append("--");
return post.ToString();
}
public static string ConvertBytesToString(byte[] bytes)
{
string output = String.Empty;
MemoryStream stream = new MemoryStream(bytes);
stream.Position = 0;
using (StreamReader reader = new StreamReader(stream))
{
output = reader.ReadToEnd();
}
return output;
}
Hammock for Windows Phone makes this real simple.
You just add the file to the request using the AddFile method and pass it the photo stream.
var request = new RestRequest("photo", WebMethod.Post);
request.AddParameter("photo_album_id", _album.album_id);
request.AddFile("photo", filename, e.ChosenPhoto);
Hum are you sure that your PostForm is correct ? The content-* params should be set in the headers of your POST and not in the body ?
var request = (HttpWebRequest)WebRequest.Create(url);
request.Headers.Add(HttpRequestHeader.Authorization,"blabla");
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";