Sending multiple parameters to POST method in .net: - rest

I'm struggling to use POST method for RESTful services. My requirement is some parameters I need to append (not in the URL) and 2 parameters I need to read from file. The service is written in Java.
string url= "http://srfmdpimd2:18109/1010-SF-TNTIN/Configurator/rest/importConfiguration/"
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
FileStream file = new FileStream(#"TestSCDS.properties", FileMode.Open);
Byte[] bytes = new Byte[file.Length];
file.Read(bytes, 0, bytes.Length);
string strresponse = Encoding.UTF8.GetString(bytes);
request.Method = "POST";
request.ContentType = "multipart/form-data;";
request.ContentLength = file.Length;
request.Headers.Add("hhrr", "H010");
request.Headers.Add("env", "TEST");
request.Headers.Add("buildLabel", "TNTAL_05.05.0500_C54");
Stream Postdata = request.GetRequestStream();
Postdata.Write(bytes, 0, bytes.Length);
HttpWebResponse response = (HttpWebResponse)request.GetResponse();`
request.Headers.Add() is adding parameters to URL? If not, how can I send multiple parameters to POST method in restful services?
Also, how to read parameters from file and make use in POST method?

It needs a little leg work, encode a dictionary and put it in the body. Below is a quick sample:
private string Send(string url)
{
HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
request.Method = "POST";
string postData = EncodeDictionary(args, false);
ASCIIEncoding encoding = new ASCIIEncoding();
byte[] postDataBytes = encoding.GetBytes(postData);
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = postDataBytes.Length;
using(Stream requestStream = request.GetRequestStream())
{
requestStream.Write(postDataBytes, 0, postDataBytes.Length);
}
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
StreamReader reader = new StreamReader(response.GetResponseStream());
return reader.ReadToEnd();
}
}
private string EncodeDictionary(Dictionary<string, string> dict,
bool questionMark)
{
StringBuilder sb = new StringBuilder();
if (questionMark)
{
sb.Append("?");
}
foreach (KeyValuePair<string, string> kvp in dict)
{
sb.Append(HttpUtility.UrlEncode(kvp.Key));
sb.Append("=");
sb.Append(HttpUtility.UrlEncode(kvp.Value));
sb.Append("&");
}
sb.Remove(sb.Length - 1, 1); // Remove trailing &
return sb.ToString();
}

I don't know what your complete requirements are, but my strong suggestion is to "start simple".
Do not use "Content-type: multipart/form-data" unless you're sure you need it. Instead, start out with "application/x-www-form-urlencoded" (an old favorite) or "application/json" (even better).
Here is a nice little step-by-step example. You can find literally 100's more with a simple Google search:
http://www.asp.net/web-api/overview/web-api-clients/calling-a-web-api-from-a-net-client

Related

SharePoint Rest Api - 403 when trying to update list item

From a C# library I need to use the SP rest Api to upload a document to a document library then set properties for it.
I almost have this working by making the following sequence of calls:
Post to /contextinfo to get the FormDigestValue
Post the binary to /Files/Add including the digest in the header property X-RequestDigest
Get /ListItemAllFields the digest in the header property X-RequestDigest
The next call is a Post to _api/web/lists/GetByTitle('library name')/Items(157)
The same digest value is included in the header property X-RequestDigest as can be seen below:
POST
https://xxx.uk/_api/web/lists/GetByTitle('AssetMgmtEfilesDemo')/Items(157) HTTP/1.1
Accept: application/json, application/xml; odata=verbose
X-HTTP-Method: MERGE
IF-MATCH: *
X-RequestDigest: 0x01426A9818F7145E12BC2E99246C7E00AC1A3905D27204C783107FDDE806D2629171FAD8DCC61008E109DD9948BEB4208DC62107B2336B1228ABA143A2D5B3C6,19 Feb 2019 15:20:44 -0000
Content-Type: application/json; charset=utf-8
Host: xxx.uk
Content-Length: 359
Expect: 100-continue
{
__metadata":{
"type":"SP.Data.AssetMgmtEfilesDemoItem"
},
"UPRN":"U1",
"KeystoneDocType":"Document"
}
My problem is that for this request, I get a "403 forbidden" response.
Can anyone see where I went wrong?
Did you try getting a fresh new form digest value before making the post call ? form digest value do expire after some time (default 30 mins).
You can also check your permission on the specific list.
Sample code for your reference, call Rest API in C# code, reference System.Web.Extensions dll:
using System.Net;
using System.IO;
using System.Web.Script.Serialization;
static void Main(string[] args)
{
UpdateListItem();
}
public static string GetFormDigest()
{
string formDigest = null;
string resourceUrl = "http://sp/sites/dev/_api/contextinfo";
HttpWebRequest wreq = HttpWebRequest.Create(resourceUrl) as HttpWebRequest;
wreq.UseDefaultCredentials = true;
wreq.Method = "POST";
wreq.Accept = "application/json;odata=verbose";
wreq.ContentLength = 0;
wreq.ContentType = "application/json";
string result;
WebResponse wresp = wreq.GetResponse();
using (StreamReader sr = new StreamReader(wresp.GetResponseStream()))
{
result = sr.ReadToEnd();
}
var jss = new JavaScriptSerializer();
var val = jss.Deserialize<Dictionary<string, object>>(result);
var d = val["d"] as Dictionary<string, object>;
var wi = d["GetContextWebInformation"] as Dictionary<string, object>;
formDigest = wi["FormDigestValue"].ToString();
return formDigest;
}
public static void UpdateListItem()
{
string result = string.Empty;
Uri uri = new Uri("http://sp/sites/dev/_api/web/lists/getbytitle('AssetMgmtEfilesDemo')/items(1)");
HttpWebRequest wreq = (HttpWebRequest)WebRequest.Create(uri);
wreq.Credentials = CredentialCache.DefaultNetworkCredentials;
wreq.Method = "POST";
wreq.Accept = "application/json; odata=verbose";
wreq.ContentType = "application/json; odata=verbose";
wreq.Headers.Add("X-HTTP-Method", "MERGE");
wreq.Headers.Add("IF-MATCH", "*");
wreq.Headers.Add("X-RequestDigest", GetFormDigest());
string stringData = "{'__metadata': { 'type': 'SP.Data.AssetMgmtEfilesDemoItem' }, 'Title': 'UpdatedViaRest','UPRN':'U1','KeystoneDocType':'Image'}";
wreq.ContentLength = stringData.Length;
StreamWriter writer = new StreamWriter(wreq.GetRequestStream());
writer.Write(stringData);
writer.Flush();
WebResponse wresp = wreq.GetResponse();
using (StreamReader sr = new StreamReader(wresp.GetResponseStream()))
{
result = sr.ReadToEnd();
}
}

Hi All, I am struggling in rest API where i need to post an XML in body with header and get the response, can anyone post an example of how to do it?

String reqURL = baseUrl + data_oauth.get(PropLoad.getTestXmlData("URL"));
Template template = new Template();
String updatedUrl = template.getUpdatedURL(reqURL);
Map<String, String> headers = Template.getRequestData(data_oauth,PropLoad.getTestXmlData("HEADER"));
headers.entrySet().toString();
String updatedAuthor = template.getAuthorizationHeader(headers, methodDesc);
headers.put("Authorization", updatedAuthor);
String xmlRequest = Template.generateStringFromResource(data_oauth,"xmlbody");
Response response = webCredentials_rest.postCallWithHeaderAndBodyParamForXml(headers, xmlRequest, updatedUrl);
// am getting Unmarshalled as in response, can any help me on posting an POST request with XML body in it
You can send it like this:
URL url = new URL(urlString);
URLConnection connenction = url.openConnection();
OutputStream output = connenction.getOutputStream();
InputStream input = new FileInputStream(xmlFile);
byte[] buffer = new byte[4096];
int len;
while ((len = input .read(buffer)) >= 0) {
out.write(buffer, 0, len);
}
input .close();
output.close();
And read the response like this:
StringBuilder stringBuilder = new StringBuilder();
BufferedReader reader = new BufferedReader(new InputStreamReader(connenction.getInputStream()));
String readLine = reader.readLine();
while (readLine != null) {
stringBuilder.append(readLine);
readLine = br.readLine();
}

How to add image file in Adobe AEM JCR using rest API from .Net

I googled alot but not getting any documentation of Adobe AEM for restfull API. I tried the .Net code from
https://helpx.adobe.com/experience-manager/using/using-net-client-application.html.
But it creates folder instead of uploading content.
What are the parameters we need to pass to upload any image, mp4, pdf etc. Below is my c# code.
protected void Button1_Click(object sender, EventArgs e)
{
string fileName=FileUpload1.FileName;
String postURL = "http://localhost:4502/content/dam/geometrixx/" + fileName;
System.Uri uri = new System.Uri(postURL);
HttpWebRequest httpWReq = (HttpWebRequest)WebRequest.Create(uri);
NetworkCredential nc = new NetworkCredential("admin", "admin");
httpWReq.Method = "POST";
httpWReq.Credentials = nc;
httpWReq.ContentType = "application/x-www-form-urlencoded";
ASCIIEncoding encoding = new ASCIIEncoding();
byte[] data = FileUpload1.FileBytes;
httpWReq.ContentLength = data.Length;
using (System.IO.Stream stream = httpWReq.GetRequestStream())
{
stream.Write(data, 0, data.Length);
}
HttpWebResponse response = (HttpWebResponse)httpWReq.GetResponse();
string responseText = string.Empty;
using (var reader = new System.IO.StreamReader(response.GetResponseStream(), encoding))
{
responseText = reader.ReadToEnd();
}
TextBox1.Text = responseText;
}
I'm not familar with .Net, but the question is more about how to create an asset in AEM. You didn't specify any version, so I tested my code only on AEM 5.6.1, but it should work also on AEM 6.X. In the following snippet you can see how you can upload new file using curl into a folder of your choice in dam, so you have only to make the call from your .Net code:
curl -u admin:admin -X POST -F file=#"/absolute/path/to/your/file.ext" http://localhost:4502/content/dam/the/path/you/wish/to/upload/myfolder.createasset.html
You are sending a POST request to the dam path where the file have to be uploaded with the selector "createasset" and the extension "html".
.net code for uploading files on Aem. Try below code.
var filelocation = AppDomain.CurrentDomain.BaseDirectory + "Images\\YourFile with Extension";
FileStream stream = File.OpenRead(filelocation);
byte[] fileBytes = new byte[stream.Length];
stream.Read(fileBytes, 0, fileBytes.Length);
stream.Close();
var httpClientHandler = new HttpClientHandler()
{
Credentials = new NetworkCredential("admin", "Your Password"),
};
//var httpClient = new HttpClient(httpClientHandler);
using (var httpClient = new HttpClient(httpClientHandler))
{
var requestContent = new MultipartFormDataContent();
var imageContent = new ByteArrayContent(fileBytes);
requestContent.Add(imageContent, "file", "file nmae with extension");
var response1 = httpClient.PostAsync("http://siteDomain/content/dam/yourfolder.createasset.html", requestContent);
var result = response1.Result.Content.ReadAsStringAsync();
}

How to add new account in Quickbooks

Below is the code I am using to try to add a new account to QuickBooks online. I am getting a (400) Bad Request. Can anyone help me with this.
HttpWebRequest httpWebRequest =
WebRequest.Create("https://sandbox-quickbooks.api.intuit.com/v3/company/xxxxxxxxxxx/account")
as HttpWebRequest;
httpWebRequest.Method = "POST";
httpWebRequest.Headers.Add("Authorization", GetDevDefinedOAuthHeader(httpWebRequest, ConsumerKeyQb, ConsumerSecQb, AccessKey, AccessSec));
httpWebRequest.ContentType = "application/json";
httpWebRequest.Accept = "application/xml";
string json = "{\"AccountType\":\"Accounts Receivable\",\"Name\":\"MySampleAccount\"}";
byte[] bytes = Encoding.UTF8.GetBytes(json);
httpWebRequest.ContentLength = bytes.Length;
using (Stream putStream = httpWebRequest.GetRequestStream())
{
putStream.Write(bytes, 0, bytes.Length);
}
HttpWebResponse httpWebResponse = null;
try
{
httpWebResponse = httpWebRequest.GetResponse() as HttpWebResponse;
}
catch (Exception e)
{
//return null;
var x = "Stop";
}
Thanks
400 response suggests that your API request payload is not correct.
You can try this call using IPP provided .net devkit.
https://developer.intuit.com/docs/0025_quickbooksapi/0055_devkits/0150_ipp_.net_devkit_3.0/0002_synchronous_calls/0001_data_service_apis
Using Dev-defined lib( sample call ) -
https://gist.github.com/IntuitDeveloperRelations/0913b4c224de758fde0a
Thanks

Malformed HTTP post using WWWForm

I'm using UnityHTTP (https://github.com/andyburke/UnityHTTP) to call a REST API ( KiiCloud http://www.kii.com ) and it works great but I want to get rid of the 3rd party library if possible and use Unity's WWW and WWWForm to achieve the same.
Here's the code that uses UnityHTTP that works fine:
public static void RunServerExtension (string appId, string appKey, string endpoint, string kii_access_token, string msg)
{
Hashtable data = new Hashtable();
// Add json fields with values here (use as dictionary)
data.Add("message", msg);
// When you pass a Hashtable as the third argument, we assume you want it send as JSON-encoded
// data. We'll encode it to JSON for you and set the Content-Type header to application/json
HTTP.Request myRequest = new HTTP.Request( "post", "https://api.kii.com/api/apps/" + appId + "/server-code/versions/current/" + endpoint, data);
myRequest.AddHeader("x-kii-appid", appId);
myRequest.AddHeader("x-kii-appkey", appKey);
if(kii_access_token != null)
theRequest.AddHeader("Authorization", "Bearer " + kii_access_token);
myRequest.Send( ( request ) => {
// we provide Object and Array convenience methods that attempt to parse the response as JSON
// if the response cannot be parsed, we will return null
// note that if you want to send json that isn't either an object ({...}) or an array ([...])
// that you should use JSON.JsonDecode directly on the response.Text, Object and Array are
// only provided for convenience
Hashtable result = request.response.Object;
if ( result == null )
{
Debug.LogWarning( "Could not parse JSON response!" );
return;
}
Debug.Log ("Got response");
Debug.Log(request.response.Text);
});
}
So the above works just fine but when I switch to WWWForm in this way:
public static WWW RunServerExtension (string appId, string appKey, string endpoint, string kii_access_token, string msg)
{
WWWForm form = new WWWForm();
Hashtable headers = form.headers;
headers["Content-Type"] = "application/json";
headers["x-kii-appid"] = appId;
headers["x-kii-appkey"] = appKey;
if(kii_access_token != null)
headers["Authorization"] = "Bearer " + kii_access_token;
form.AddField("message", msg);
return new WWW("https://api.kii.com/api/apps/" + appId + "/server-code/versions/current/" + endpoint, form.data, headers);
}
private IEnumerator WaitForRequest(WWW www)
{
yield return www;
// check for errors
if (www.error == null)
{
Debug.Log("WWW Ok!: " + www.text);
} else {
Debug.Log("WWW Error: "+ www.error);
}
}
I get a BAD REQUEST on the server side (meaning the request is malformed, not what the server was expecting). Note that the headers must be passed as parameter otherwise the server complains about missing headers.
I suspected this might be related to the fact that the server expects JSON data so I converted the message to JSON using UnityHTTP JSON class (you can use just that isolated class for JSON encoding/decoding) https://github.com/andyburke/UnityHTTP/blob/master/external/JSON.cs so this method passes {"message":"This is echoed!!"} as data:
public static WWW RunServerExtension (string appId, string appKey, string endpoint, string kii_access_token, string msg)
{
WWWForm form = new WWWForm();
Hashtable headers = form.headers;
headers["Content-Type"] = "application/json";
headers["x-kii-appid"] = appId;
headers["x-kii-appkey"] = appKey;
if(kii_access_token != null)
headers["Authorization"] = "Bearer " + kii_access_token;
Hashtable data = new Hashtable();
data["message"] = msg;
byte[] bytes = GetBytes(JSON.JsonEncode(data));
return new WWW("https://api.kii.com/api/apps/" + appId + "/server-code/versions/current/" + endpoint, bytes, headers);
}
static byte[] GetBytes(string str)
{
byte[] bytes = new byte[str.Length * sizeof(char)];
System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length);
return bytes;
}
But still the same BAD REQUEST. Do you see why this could be failing? Why UnityHTTP works?
As I mentioned in comments: C# converts all strings to UTF-16. If your webserver is expecting a different encoding, simply passing the bytes verbatim will not produce good results.
JSON is typically encoded in UTF-8, but it's best if an API specifies its input/output encodings explicitly.
I took a bit more time, today. If you check UnityHTTP's source, you can see that their Hashtable constructor encodes JSON in UTF-8:
this.bytes = Encoding.UTF8.GetBytes( JSON.JsonEncode( data ) );
Your code does not change the string's encoding, which means you're sending the wrong bytes.