I am trying to create a new document in documentDB via the rest API. I would use the SDK, but im running the project from asp.net core and the SDK isn't compatible yet.
I would like to have documentDB auto generate the id for the document, but I am having problems with my request.
What should I set the ids value to when creating the document via the documentDB rest api (using id based routing)?
Right now I am getting hit with the 400 bad request error.
Ive tried posting it with the following variations on the id:
No id property
id: null
id: ""
The code i am using is basically what was in the github .net rest examples, i have the replace call, get calls working fine.
Here is my code making the request:
//Create a document
verb = "POST";
resourceType = "docs";
resourceLink = string.Format("dbs/{0}/colls/{1}/docs", databaseId, collectionId);
resourceId =string.Format("dbs/{0}/colls/{1}", databaseId, collectionId);
authHeader = GenerateMasterKeyAuthorizationSignature(verb, resourceId, resourceType, masterKey, "master", "1.0");
client.DefaultRequestHeaders.Remove("authorization");
client.DefaultRequestHeaders.Add("authorization", authHeader);
string content = JsonConvert.SerializeObject(document);
StringContent contentMessage = new StringContent(content, System.Text.Encoding.UTF8, "application/json");
contentMessage.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");
contentMessage.Headers.ContentType.CharSet = null;
var r = client.PostAsync(baseUri + resourceLink, contentMessage).Result;
System.Diagnostics.Debug.WriteLine(r.Content.ReadAsStringAsync().Result);
return r.Content.ReadAsStringAsync().Result;
You should supply a string value for the "id" property. The auto-id functionality (like Larry mentions) is a client-side feature, not part of the REST API. So when consuming directly from REST, you must generate a Guid (or any unique string) and set the "id" property with that value.
Related
I am pulling my hair out trying to query the CoinSpot API.
The endpoint for the Read Only API is: https://www.coinspot.com.au/api/ro
The documentation states:
All requests to the API will need to include the following security
data.
Headers: key - Your API key generated from the settings page sign -
The POST data is to be signed using your secret key according to
HMAC-SHA512 method. Post Params: nonce - Any integer value which must
always be greater than the previous requests nonce value.
I try to query the 'List My Balances' endpoint via: https://www.coinspot.com.au/api/ro/my/balances
However, the code I have formulated below always returns an error: "invalid/missing nonce".
I have tried so many different variations and approaches but it is always the same error.
require(httr)
key <- "68z...39k"
secret <- "71A...48i"
result <- POST("https://www.coinspot.com.au/api/ro/my/balances",
body = list('nonce'=as.integer(as.POSIXct(Sys.time()))), add_headers("key"=key,"sign"=openssl::sha512("https://www.coinspot.com.au/api/ro/my/balances",key = secret)))
content(result)
Any help much appreciated.
Ive struggled with this too- the coinspot API guide isn't very clear.
I figured out you are meant to encode the postdata in correct json format using sha512 and add that to the sign header. See example below querying account balances on v2 of the api.
require(httr)
api_key = "68z...39k"
api_secret = "71A...48i"
base_url = "https://www.coinspot.com.au/api/v2/ro"
request = "/my/balances"
nonce = as.character(as.integer(Sys.time()))
postdata = paste0('{"nonce":"',nonce,'"}') # important to get the quotes correct
api_sign = digest::hmac(api_secret, postdata, algo="sha512",raw=F)
result = POST(paste0(base_url, request),
body = list("nonce"=nonce),
add_headers(c("key"=api_key,
"sign"=api_sign)),
encode="json"
)
cat(rawToChar(result$content))
You would change what is in postdata based on what you are doing with the API- this is a simple example to build on. If you want to see what postdata should look like prior to encryption in sign, use cat(rawToChar(result$request$options$postfields)) after making a request.
For me, I was missing the JSON string encoded postdata in the body, including the nonce. As soon as I added that, it started working.
Heres my code in c# using Restsharp and Newtonsoft
//put the nonce at the beginning
JObject joBody = JObject.Parse(#"{'nonce': '" + DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString() + "'}");
joBody.Merge(originalBody);
var client = new RestClient(_coinspotSettings.BaseURL);
RestRequest request = new RestRequest(endpoint, Method.POST);
request.AddJsonBody(JsonConvert.SerializeObject(joBody));
request.AddHeader("key", coinspotAccount.APIKey);
request.AddHeader("sign", SignData(coinspotAccount, Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(joBody))).ToLower());
request.AddHeader("Content-Type", "application/json");
private string SignData(CoinspotAccount coinspotAccount, byte[] JSONData)
{
var HMAC = new HMACSHA512(Encoding.UTF8.GetBytes(coinspotAccount.APISecret));
byte[] EncodedBytes = HMAC.ComputeHash(JSONData);
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i <= EncodedBytes.Length - 1; i++)
stringBuilder.Append(EncodedBytes[i].ToString("X2"));
return stringBuilder.ToString();
}
i want to get complete list of followers using REST API with c# but i only get 20 followers
var postBody = "screen_name=" + Uri.EscapeDataString(screen_name);//
resource_url += "?" + postBody;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(resource_url);
request.Headers.Add("Authorization", authHeader);
request.Method = "GET";
request.ContentType = "application/x-www-form-urlencoded";
var response = (HttpWebResponse)request.GetResponse();
string result = new StreamReader(response.GetResponseStream()).ReadToEnd();
JObject j = JObject.Parse(result);
JArray data = (JArray)j["users"];
So with the above codes, i get only 20 followers and from here i see in an answer there is a broken link to a package. Also, i am using only Newton.Json. How do i get complete list of followers?
you have to add parameters to your query with the cursor provided in the json returned in your first query.
https://dev.twitter.com/rest/reference/get/followers/ids
I am not sure I do understand what your problem is. But getting all the followers of a member is not a 'simple' process.
I would suggest that you try out the project Tweetinvi and learn more about this feature here : https://github.com/linvi/tweetinvi/wiki/Get-All-Followers-Code.
You will first want to get all the users ids and then get the user objects via.
Then you can use var userIds = User.GetUsersFromIds(userIds); to get the users from Followers.
NOTE : Remember that Twitter has rate limits on its API. Take a look at https://github.com/linvi/tweetinvi/wiki/Rate-Limits to learn how to use them.
For simplicity I would suggest that you use :
RateLimit.RateLimitTrackerMode = RateLimitTrackerMode.TrackAndAwait;
So my problem is little bit complicated.
Main goal: register account (class / table) that contains list of Players (class / table) from a web application into a SQL Server database through a WCF service.
So for creating the classes I used Linq-to-SQL which created the Account and Player class. The Player has a foreign key AccountEmail to the Account table. Due to that the class Account has EntitySet<Player> _Players;.
Now the web application has reference to this service and when user finish registration I am making an POST request with WebClient and DataContractJsonSerializer to the service .
Unfortunately the service or the http protocol cannot understand the request :
System.Net.WebException: The remote server returned an error: (400)
Full error response from server
https://s31.postimg.org/x6b27uqqj/errorrr.png
The fail is on service side for some reason it doesn't know how to read the json player DB.designer.cs:line 295 at ReadPlayerFromJson(XmlReaderDelegator
Service:
[OperationContract]
[WebInvoke(UriTemplate = "/Register",
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json, Method = "POST")]
void RegisterAccount(Account account);
Client side :
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(Account));
MemoryStream mem = new MemoryStream();
Account a = new Account { EMAIL = Email.Text, PASSWORD = Password.Text, NAME = nickname.Text};
a.Players = accountPLayers.ToArray();
ser.WriteObject(mem, a);
string data = Encoding.UTF8.GetString(mem.ToArray(), 0, (int)mem.Length);
WebClient webClient = new WebClient();
webClient.Headers["Content-type"] = "application/json";
webClient.Encoding = Encoding.UTF8;
webClient.UploadString(WEB_SITE_URL+ "/Register", "POST", data);
When sending Account without the list of players, the operation succeeds:
{"EMAIL":"test#gmail.com","NAME":"1","PASSWORD":"test","Players":null}
With the list of players the operation fails :
{"EMAIL":"test#gmail.com","NAME":"1","PASSWORD":"test","Players":[{"Account":null,"AccountEmail":"test#gmail.com","FirstName":"test","Id":0,"LastName":"test","Type":-1}]}
Questions:
I guess that REST service expecting to get only Account and doesn't know what is the list of players? I have to define that somehow.
Why in the service does the Account have EntitySet<Player> _Players;? And in the client after adding reference to service it is an array Player[] ?
Why does Linq-to-SQL add field Account to player? What should it contain? As you can see this field is null in the json.
Is complex object/known types has to do something with my problem ?
Please help me to solve this issue, thanks!
Solved !!!
So if any one ever will get this problem ,
The thing is that player has foreign key of EMAIL column to Account Email .
When you create your JSON DO NOT PUT EMAIL INSIDE EACH PLAYER
LINQTOSQL knows the association and will add it automatically when parsing the JSON .
So my JSON Sent to the service looks like this :
{"EMAIL":"test#gmail.com","NAME":"test","PASSWORD":"test#A","Players":[{"Account":null,"AccountEmail":null,"FirstName":"wow","Id":0,"LastName":"koko","Type":null}]}.
I am attempting to create a DocuSign envelope from a template document using the CreateEnvelopeFromTemplates method, available within their v3 SOAP API web service. This is being instantiated from a asp.NET v4.0 web site.
Upon calling the method armed with the required parameter objects being passed in. I am recieving an exception from the web service, basically telling me that the Template ID is not a valid GUID.
669393: Guid should contain 32 digits with 4 dashes (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx).
Line 14889:
Line 14890: public DocuSignDSAPI.EnvelopeStatus CreateEnvelopeFromTemplates(DocuSignDSAPI.TemplateReference[] TemplateReferences, DocuSignDSAPI.Recipient[] Recipients, DocuSignDSAPI.EnvelopeInformation EnvelopeInformation, bool ActivateEnvelope) {
Line 14891: return base.Channel.CreateEnvelopeFromTemplates(TemplateReferences, Recipients, EnvelopeInformation, ActivateEnvelope);
Line 14892: }
Line 14893:
The template reference, a guid. Must be specified as the "Template" string property against TemplateReference object. This is then added to a dynamic array of TemplateReferences, which is one of the input parameters of the CreateEnvelopeFromTemplates method.
Actual template GUID: f37b4d64-54e3-4723-a6f1-a4120f0e9695
I am building up my template reference object using the following function that i wrote to try and make the functionality reusable:
Private Function GetTemplateReference(ByVal TemplateID As String) As TemplateReference
Dim templateReference As New TemplateReference
Dim guidTemplateID As Guid
With TemplateReference
.TemplateLocation = TemplateLocationCode.Server
If Guid.TryParse(TemplateID, guidTemplateID) Then
.Template = guidTemplateID.ToString
End If
End With
Return TemplateReference
End Function
The TemplateID is being passed in from a appSetting configuration value at the time of the TemplateReferences array instantiation like so...
templateReferences = New TemplateReference() {GetTemplateReference(ConfigurationManager.AppSettings("DocuSignTemplate_Reference"))}
recipients = New Recipient() {AddRecipient("myself#work.email", "My Name")}
envelopeInformation = CreateEnvelopeInformation()
envelopeStatus = client.CreateEnvelopeFromTemplates(templateReferences, recipients, envelopeInformation, True)
As you can see from my GetTemplateReference function I am also parsing the GUID before setting it back as a string so i know its valid. The template is managed and stored at the DocuSign end, hence specifying the document location.
I am referring to their own documentation:
CreateEnvelopeFromTemplates
Why oh why is the method not liking my Template ID? I can successfully use their REST API to call the same method, using their own code samples. Worst case I can make use of this but would rather interact with the web service as I would need to construct all the relevent requests in either XML or JSON.
I would really appreciate if someone could perhaps shed some light on this problem.
Thanks for taking the time to read my question!
Andrew might be spot on with the AccountId mention - are you setting the AccountId in the envelope information object? Also, have you seen the DocuSign SOAP SDK up on Github? That has 5 sample SOAP projects including one MS.NET project. The .NET project is in C# not Visual Basic, but still I think it will be helpful to you. Check out the SOAP SDK here:
https://github.com/docusign/DocuSign-eSignature-SDK
For instance, here is the test function for the CreateEnvelopeFromTemplates() function:
public void CreateEnvelopeFromTemplatesTest()
{
// Construct all the recipient information
DocuSignWeb.Recipient[] recipients = HeartbeatTests.CreateOneSigner();
DocuSignWeb.TemplateReferenceRoleAssignment[] finalRoleAssignments = new DocuSignWeb.TemplateReferenceRoleAssignment[1];
finalRoleAssignments[0] = new DocuSignWeb.TemplateReferenceRoleAssignment();
finalRoleAssignments[0].RoleName = recipients[0].RoleName;
finalRoleAssignments[0].RecipientID = recipients[0].ID;
// Use a server-side template -- you could make more than one of these
DocuSignWeb.TemplateReference templateReference = new DocuSignWeb.TemplateReference();
templateReference.TemplateLocation = DocuSignWeb.TemplateLocationCode.Server;
// TODO: replace with template ID from your account
templateReference.Template = "server template ID";
templateReference.RoleAssignments = finalRoleAssignments;
// Construct the envelope information
DocuSignWeb.EnvelopeInformation envelopeInfo = new DocuSignWeb.EnvelopeInformation();
envelopeInfo.AccountId = _accountId;
envelopeInfo.Subject = "create envelope from templates test";
envelopeInfo.EmailBlurb = "testing docusign creation services";
// Create draft with all the template information
DocuSignWeb.EnvelopeStatus status = _apiClient.CreateEnvelopeFromTemplates(new DocuSignWeb.TemplateReference[] { templateReference },
recipients, envelopeInfo, false);
// Confirm that the envelope has been assigned an ID
Assert.IsNotNullOrEmpty(status.EnvelopeID);
Console.WriteLine("Status for envelope {0} is {1}", status.EnvelopeID, status.Status);
}
This code calls other sample functions in the SDK which I have not included, but hopefully this helps shed some light on what you're doing wrong...
This problem arises when you don't set up the field AccountId. This field can be retrieved from your account. In Docusign's console go to Preferences / API and look here
Where to find AccountID Guid in Docusign's Console
Use API Account ID (which is in GUID format) and you should be OK.
Our Situation:
Our team needs to retrieve log information from a 3rd party website (Specifically, this log
information is call logs -- our client rents an 866 number. When calls come in, they assist
people and need to make notes accordingly in our application that will correspond with the
current call). Our client has a web account with the 3rd party that allows them to view the
current call logs (date/time, phone number, amount of time on each call, etc).
I contacted the developer of their website and inquired about API or any other means of syncing
our database with their constantly updating database. They currently DO NOT support API. I
informed them of my situation and they are perfectly fine with any way we can retrieve the
information (bot/crawler). *The 3rd party said that they are working on API but could not give
us a general timeline as to when it will be up... and as with every client, they need to start
production ASAP.
I completely understand that if the 3rd party were to change their HTML layout, it may cause a
slight headache for us (sorting the data from the webpage). That being said, this is a temporary
solution to a long term issue. Once they implement their API, we will switch them over to it.
So my question is this:
What is the best way to log into the 3rd party website (see image: http://i903.photobucket.com/albums/ac239/jreedinc/customtf.jpg)
and retrieve certain HTML pages? We have reviewed source codes of webcrawlers, but none of them
have the capability of storing cookies and posting information back to the website (with log in information). We would prefer to do this in ASP.NET.
Is there another way to accomplish logging on to the website, then retrieving said information?
The classes you'll need to use are in the System.Net namespace. Below is some quick and dirty proof of concept code. To login in to a site that uses form login + cookies for security and then scrape the HTML output of a page.
In order to parse the HTML results you'll need to use an additional tool.
Possible HTML parsing tools.
SgmlReader, can convert HTML to XML. You then use .NET's XML features to extract data from the XML.
http://code.msdn.microsoft.com/SgmlReader
HTML Agility Pack, allows XPath queries against HTML documents.
http://htmlagilitypack.codeplex.com/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
class WebWorker {
/// <summary>
/// Cookies for use by web worker
/// </summary>
private System.Collections.Generic.List `<System.Net.Cookie` > cookies = new List < System.Net.Cookie > ();
public string GetWebPageContent(string url) {
System.Net.HttpWebRequest request = (System.Net.HttpWebRequest) System.Net.WebRequest.Create(url);
System.Net.CookieContainer cookieContainer = new System.Net.CookieContainer();
request.CookieContainer = cookieContainer;
request.Method = "GET";
//add cookies to maintain session state
foreach(System.Net.Cookie c in this.cookies) {
cookieContainer.Add(c);
}
System.Net.HttpWebResponse response = request.GetResponse() as System.Net.HttpWebResponse;
System.IO.Stream responseStream = response.GetResponseStream();
System.IO.StreamReader sReader = new System.IO.StreamReader(responseStream);
System.Diagnostics.Debug.WriteLine("Content:\n" + sReader.ReadToEnd());
return sReader.ReadToEnd();
}
public string Login(string url, string userIdFormFieldName, string userIdValue, string passwordFormFieldName, string passwordValue) {
System.Net.HttpWebRequest request = (System.Net.HttpWebRequest) System.Net.WebRequest.Create(url);
System.Net.CookieContainer cookieContainer = new System.Net.CookieContainer();
request.CookieContainer = cookieContainer;
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
string postData = System.Web.HttpUtility.UrlEncode(userIdFormFieldName) + "=" + System.Web.HttpUtility.UrlEncode(userIdValue) +
"&" + System.Web.HttpUtility.UrlEncode(passwordFormFieldName) + "=" + System.Web.HttpUtility.UrlEncode(passwordValue);
request.ContentLength = postData.Length;
request.AllowAutoRedirect = false; //allowing redirect seems to loose cookies
byte[] postDataBytes = System.Text.Encoding.UTF8.GetBytes(postData);
System.IO.Stream requestStream = request.GetRequestStream();
requestStream.Write(postDataBytes, 0, postDataBytes.Length);
System.Net.HttpWebResponse response = request.GetResponse() as System.Net.HttpWebResponse;
// System.Diagnostics.Debug.Write(WriteLine(new StreamReader(response.GetResponseStream()).ReadToEnd());
System.IO.Stream responseStream = response.GetResponseStream();
System.IO.StreamReader sReader = new System.IO.StreamReader(responseStream);
System.Diagnostics.Debug.WriteLine("Content:\n" + sReader.ReadToEnd());
this.cookies.Clear();
if (response.Cookies.Count > 0) {
for (int i = 0; i < response.Cookies.Count; i++) {
this.cookies.Add(response.Cookies[i]);
}
}
return "OK";
}
} //end class
//sample to use class
WebWorker worker = new WebWorker();
worker.Login("http://localhost/test/default.aspx", "uid", "bob", "pwd", "secret");
worker.GetWebPageContent("http://localhost/test/default.aspx");
I used a tool recently called WebQL (its a web scraper tool that lets the developer use SQL like syntax to scrape information from web pages.
WebQL on Wikipedia
This is actually a relatively simple operation. What you need to do is get the page that the screenshot posts back to (something like login.php, etc) and then construct a webrequest to that page with the login data you have. You will most likely get back a cookiecontainer that will have your login cookie to use on all subsequent requests.
You can look at this MSDN article for the basics of how to do it, but their write-up is kind of confusing. Look at the community comments at the end for an example of how to post back page variables (like the username and password). You will need to make sure you pass the cookiecontainer around on subsequent requests.
Unfortunately .NET does not natively have something like WWW::Mechanize, but the Webclient does have an "upload value" which might make it easier. You will still have to manually parse the page to figure out what fields you need to pass.