stackoverflow search api - c#

I would like to use the search method of stackoverflow API to return the json structure of results based on a search keyword and then display those results (title, description and the url) in the SearchResults div.
I am new to C# and my first attempt went something like this:
protected void searchStockOverflow(string y)
{
var httpWebRequest = (HttpWebRequest)WebRequest.Create("http://api.stackoverflow.com/1.1/search?intitle="+y);
httpWebRequest.ContentType = "text/json";
httpWebRequest.Method = "POST";
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
string json = "{ \"intitle\": \"" + y + "\"}";
streamWriter.Write(json);
}
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var responseText = streamReader.ReadToEnd();
SearchResults.InnerHtml += "<div style='border:1px solid blue;margin:5px;'>";
SearchResults.InnerHtml += responseText + "<br />";
SearchResults.InnerHtml += "</div><br style='clear:both;' />";
}
}
The issue is that what is returned looks like dingbats rubbish - i guess because it is serialized and need to be deserialized?

I would definitely say consider using the REST client; however, to look at the issues... generally you want to deserialize the data as JSON manually, then run that data through your UI code. For example:
static void SearchStackOverflow(string y)
{
var httpWebRequest = (HttpWebRequest)WebRequest.Create("http://api.stackoverflow.com/1.1/search?intitle=" + Uri.EscapeDataString(y));
httpWebRequest.AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip;
httpWebRequest.Method = "GET";
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
string responseText;
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
responseText = streamReader.ReadToEnd();
}
var result = (SearchResult)new JavaScriptSerializer().Deserialize(responseText, typeof(SearchResult));
.... do something with result ...
}
class SearchResult
{
public List<Question> questions { get; set; }
}
class Question
{
public string title { get; set; }
public int answer_count { get; set; }
}
Which uses the JavaScriptSerializer from System.Web.Extensions.dll

Also Take a look at Stacky StackApps .Net Client Library which is REST-based API that provides access to stackoverflow family of websites.

Unfortunately I'm on my Mac and can't run a test on your code. You might want to check the character encoding of both your page and the response stream coming back. If they don't match; it could cause the characters coming from the response stream to be rendered incorrectly, hence the rubbish you're seeing.

Related

Slack Integration - How to notify user with # when posted to channel

I have this code that notifies a slack channel after a build has completed. In certain cases, whenever the build fails, I want to add a notification to myself so I can quickly turn issues around. How can I update this to include a notification to someone using the # symbol?
Some examples I see online use the SlackMessage constructor to add a userName, but for some reason I can not overload this constructor.
public static void PostToSlack()
{
string url= "...";
string slackUrl = GlobalData.slackUrl;
string buildName = TestContext.Parameters["BuildName"];
string buildID = TestContext.Parameters["BuildID"];
string testName = TestContext.CurrentContext.Test.Name;
string outcome = TestContext.CurrentContext.Result.Outcome.ToString();
//If tests failed but the suite actually completed, set more understandable outcome message
if (outcome == "Failed(Child)")
{
outcome = "Completed with Issues";
}
//Build the text string to post to slack
string postText = "Build Completed";
SlackMessage message = new SlackMessage
{
text = postText
};
//Convert serializable object to JSON
string json = JsonConvert.SerializeObject(message, Newtonsoft.Json.Formatting.Indented);
var httpWebRequest = (HttpWebRequest)WebRequest.Create(slackUrl);
httpWebRequest.ContentType = "application/json";
httpWebRequest.Method = "POST";
//Send to Slack
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
streamWriter.Write(json);
streamWriter.Flush();
streamWriter.Close();
}
//Error checking if Slack sends back a 404 or 400
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var result = streamReader.ReadToEnd();
}
}

Unable to Post on Pinterest using their API

I'm receiving a 400 Bad Request error message when posting a pin on Pinterest. It works using Postman, but doesn't work programmatically. Using C#, has anyone been able to successfully post a pin on Pinterest without using the pinsharp wrapper?
private void postPinterest(string messages, string id, string usertoken, string image, string boardname, string username)
{
string link = null;
boardname = boardname.Replace(" ", "-");
string board = username + "/" + boardname;
string url = "https://api.pinterest.com/v1/pins?access_token=" + usertoken;
StringBuilder sb = new StringBuilder();
if (!string.IsNullOrEmpty(board))
sb.Append("&board=" + HttpUtility.UrlEncode(board));
if (!string.IsNullOrEmpty(messages))
sb.Append("&note=" + HttpUtility.UrlEncode(messages));
if (!string.IsNullOrEmpty(link))
sb.Append("&image_url=" + HttpUtility.UrlEncode(link));
string postdata = sb.ToString().Substring(1);
PostData(url, postdata);
}
private object PostData(string url, string postdata)
{
object json=null;
try
{
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
req.Method = "POST";
req.ContentType = "application/x-www-form-urlencoded";
// req.Accept = "application/json";
using (var stream = req.GetRequestStream())
{
byte[] bindata = Encoding.ASCII.GetBytes(postdata);
stream.Write(bindata, 0, bindata.Length);
}
HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
string response = new StreamReader(resp.GetResponseStream()).ReadToEnd();
json = JsonConvert.DeserializeObject<dynamic>(response);
return json;
}
catch (WebException wex)
{
if (wex.Response != null)
{
using (var errorResponse = (HttpWebResponse)wex.Response)
{
using (var reader = new StreamReader(errorResponse.GetResponseStream()))
{
string error = reader.ReadToEnd();
return json;
}
}
}
}
return json;
}
EDIT:
It doesn't work using the JSON format or x-www-form-urlencoded format.
I changed the content type to application/x-www-form-urlencoded and now I'm receiving the error message below. I receive 400 Bad Request error using JSON format:
"{\n \"message\": \"405: Method Not Allowed\",\n \"type\": \"http\"\n}"
The problem is the the parameter that you are posting.
In the Api i could find board as a parameter but both note and image comes under field parameter which specifies the return type JSON.
As per documentation on this page you can post in this format
https://api.pinterest.com/v1/boards/anapinskywalker/wanderlust/pins/?
access_token=abcde&
limit=2&
fields=id,link,counts,note
So I tried the following and its getting response
https://api.pinterest.com/v1/boards/?access_token="YourTokenWithoutQuotes"&fields=id%2Ccreator
Would suggest you to first test the Api you are hitting putting a breakpoint inside the PostData function and check if the passed url is in the correct format and compare it with Pininterest API Explorer.
As you might have already received authorization code and access token so I am assuming your post function should be working fine.
public string postPinterest(string access_token,string boardname,string note,string image_url)
{
public string pinSharesEndPoint = "https://api.pinterest.com/v1/pins/?access_token={0}";
var requestUrl = String.Format(pinSharesEndPoint, accessToken);
var message = new
{
board = boardname,
note = note,
image_url = image_url
};
var requestJson = new JavaScriptSerializer().Serialize(message);
var client = new WebClient();
var requestHeaders = new NameValueCollection
{
{"Content-Type", "application/json" },
{"x-li-format", "json" }
};
client.Headers.Add(requestHeaders);
var responseJson = client.UploadString(requestUrl, "POST", requestJson);
var response = new JavaScriptSerializer().Deserialize<Dictionary<string, object>>(responseJson);
return response;
}

Retrieve all instances of recurring event via CSOM

I need to get all the instances of a recurring calendar event in Sharepoint 2013 online via CSOM. I read that it can't be done, that I need to do it via REST API directly.
My question:
1) Is it possible to get the items from a View instead of from a List, because the calendar comes with a default view where I can see all instances of the recurring event
2) I have an example of retrieveing data via REST un C# that's working fine, but I can't seem to add a Caml Query to it (in C#)
here's my non-working code:
HttpWebRequest itemRequest =
(HttpWebRequest)HttpWebRequest.Create(sharepointUrl.ToString() + "/_api/Web/lists/getbytitle('" + listName + "')/Items");
itemRequest.Method = "POST";
itemRequest.Accept = "application/atom+xml";
itemRequest.ContentType = "application/atom+xml;type=entry";
itemRequest.Headers.Add("Authorization", "Bearer " + accessToken);
using (var writer = new StreamWriter(itemRequest.GetRequestStream()))
{
writer.Write(#"{ 'query' : {'__metadata': { 'type': 'SP.CamlQuery' }, 'ViewXml': '<View><Query><Where><Eq><FieldRef Name='Title'/><Value Type='Text'>little test</Value></Eq></Where></Query></View>' } }");
}
HttpWebResponse itemResponse = (HttpWebResponse)itemRequest.GetResponse();
I get 500 Internal server error
Any thoughts??
thank you
I would recommend to utilize Fiddler to inspect REST SharePoint RESTfull web service requests.
In your case the endpoint is not correct. Since you need to request list items via CAML query, replace endpoint url from:
/_api/Web/lists/getbytitle('" + listName + "')/Items
to this one:
/_api/Web/lists/getbytitle('" + listName + "')/getitems
Secondly, application/atom+xml;type=entry HTTP Content-Type header is not supported in POST requests (see the list of supported MIME types below). So, replace the lines:
itemRequest.Accept = "application/atom+xml";
itemRequest.ContentType = "application/atom+xml;type=entry";
for example, with these ones:
itemRequest.Accept = "application/json";
itemRequest.ContentType = "application/json";
That's it.
The list of supported MIME types
application/json;odata=minimalmetadata;streaming=true
application/json;odata=minimalmetadata;streaming=false
application/json;odata=minimalmetadata
application/json;odata=fullmetadata;streaming=true
application/json;odata=fullmetadata;streaming=false
application/json;odata=fullmetadata
application/json;odata=nometadata;streaming=true
application/json;odata=nometadata;streaming=false
application/json;odata=nometadata
application/json;streaming=true
application/json;streaming=false
application/json;odata=verbose
application/json
You could also utilize the following class for performing REST requests:
public class SPRestExecutor
{
public SPRestExecutor(Uri webUri,string accessToken)
{
WebUri = webUri;
AccessToken = accessToken;
}
public JObject ExecuteJsonWithDigest(string endpointUrl, HttpMethod method, IDictionary<string, string> headers, JObject payload)
{
var formDigestValue = RequestFormDigest();
var finalHeaders = new Dictionary<string, string>();
if (headers != null)
{
foreach (var key in headers.Keys)
{
finalHeaders.Add(key, headers[key]);
}
}
finalHeaders.Add("X-RequestDigest", formDigestValue);
var result = ExecuteJson(endpointUrl, method, finalHeaders, payload);
return result;
}
public JObject ExecuteJson(string endpointUrl, HttpMethod method, IDictionary<string, string> headers, JObject payload)
{
var request = (HttpWebRequest)WebRequest.Create(WebUri.ToString() + endpointUrl);
request.Headers.Add(HttpRequestHeader.Authorization, "Bearer " + AccessToken);
request.Method = method.Method;
request.Accept = "application/json;odata=verbose";
request.ContentType = "application/json;odata=verbose";
if (payload != null)
{
using (var writer = new StreamWriter(request.GetRequestStream()))
{
writer.Write(payload);
writer.Flush();
}
}
using (var response = (HttpWebResponse)request.GetResponse())
{
using(var responseStream = response.GetResponseStream())
{
using (var reader = new StreamReader(responseStream))
{
var result = reader.ReadToEnd();
return JObject.Parse(result);
}
}
}
}
/// <summary>
/// Request Form Digest
/// </summary>
/// <returns></returns>
protected string RequestFormDigest()
{
var result = ExecuteJson("/_api/contextinfo", HttpMethod.Post, null, null);
return result["d"]["GetContextWebInformation"]["FormDigestValue"].ToString();
}
public string AccessToken { get; private set; }
public Uri WebUri { get; private set; }
}
Gist
Usage
var client = new SPRestExecutor(webUri,accessToken);
var payload = JObject.Parse(#"{ 'query' : {'__metadata': { 'type': 'SP.CamlQuery' }, 'ViewXml': '<View><Query/></View>' } }");
var data = client.ExecuteJson("/_api/web/lists/getbytitle('Documents')/getitems", HttpMethod.Post, null, payload);
Thank you Vadim Gremyachev, your post got me on track.
I had 3 problems, the first one was calling "Items" instead of "getItems", and the second one was using "application/atom+xml;type=entry" as a ContentType (just as Vadim stated).
The third and last problem, was using simple quotes all over the query. Inside the ViewXml, I used scaped double quotes so they were not confused with the one closing the ViewXml element.
So, the working code ended up being like this:
byte[] data = new ASCIIEncoding().GetBytes("{ 'query' : {'__metadata': { 'type': 'SP.CamlQuery' }, 'ViewXml': '<View><Query><Where><Eq><FieldRef Name=\"Title\"/><Value Type=\"Text\">little test</Value></Eq></Where></Query></View>' } }");
HttpWebRequest itemRequest =
(HttpWebRequest)HttpWebRequest.Create(sharepointUrl.ToString() + "/_api/Web/lists/getbytitle('" + listName + "')/getitems");
itemRequest.Method = "POST";
itemRequest.ContentType = "application/json; odata=verbose";
itemRequest.Accept = "application/atom+xml";
itemRequest.Headers.Add("Authorization", "Bearer " + accessToken);
itemRequest.ContentLength = data.Length;
Stream myStream = itemRequest.GetRequestStream();
myStream.Write(data, 0, data.Length);
myStream.Close();
HttpWebResponse itemResponse = (HttpWebResponse)itemRequest.GetResponse();

Error in json post request for mailchimp api

I am trying to create a wrapper for:
this mailchimp method using C#.Net
I understand that there are already .Net wrappers available. I am using Mailchimp.Net by Dan Esparza. Method in the wrapper class is giving exception for the api method mentioned above.It is throwing internal server exception (500) which I am not sure why, so I decided to create my own wrapper for the particular method. I have following code:
private void CreateGrouping(string apiKey, string listId,string groupName,string groupValue)
{
string url = "https://us9.api.mailchimp.com/2.0/lists/interest-grouping-add";
var httpWebRequest = (HttpWebRequest)WebRequest.Create(url);
httpWebRequest.ContentType = "text/json";
httpWebRequest.Method = "POST";
List<string> values = new List<string>();
values.Add(groupValue);
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
string json = new JavaScriptSerializer().Serialize(new
{
apiKey = apiKey,
id = listId,
name = groupName,
type="radio",
groups = values
});
streamWriter.Write(json);
}
var response = (HttpWebResponse)httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(response.GetResponseStream()))
{
var result = streamReader.ReadToEnd();
}
}
But on execution of var response = (HttpWebResponse)httpWebRequest.GetResponse(); is throwing same exception - internal server error (500).
It might be that I am passing data in wrong way ? Can someone please help me in finding out what am I missing here ?
As I suspected I was passing the data in wrong way: apiKey has to be apikey (k was in caps)
string json = new JavaScriptSerializer().Serialize(new
{
apikey = apiKey,
id = listId,
name = groupName,
type="radio",
groups = values
});
Other than this, I added:
streamWriter.Flush();
streamWriter.Close();
It might help someone save sometime.

Convert C# datetime to Json serialized Date Format

i need some help here
I am trying to make an API call by sending a json object to it.
but i am struggling to convert C# datetime to proper json format.
Here is my Sample Code.
HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create("example.com");
httpWebRequest.ContentType = "text/json";
httpWebRequest.Method = "POST";
using (StreamWriter streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
string json = "{\"ReferenceNumber\":\"Testing OAKLAND\",\"CustomerNotes\":\"Testing\",\"DeliveryDate\":" + "Date(" + System.DateTime.Now.Ticks + ")" +
",\"OrderLineItems\":[{\"ItemEntityId\":14771,\"Quantity\":2}]}";
streamWriter.Write(json);
streamWriter.Close();
}
HttpWebResponse httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (StreamReader streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
string responseText = streamReader.ReadToEnd();
Response.Write(responseText);
Response.End();
}
Please guide me how to format datetime in json and do u guys think that json this json object is fine?? I am Using .NET 2.0 Framework
Use serialization instead. It will handle any escaping and converting you need to do.
For .NET 2.0 you don't have the luxury of anonymous types, so you will have to create a model class for the data you want to serialize:
public class OrderModel {
private string _referenceNumber;
public string ReferenceNumber {
get { return _referenceNumber; }
set { _referenceNumber = value; }
}
...
class OrderItem {
private int _itemEntityId;
public int ItemEntityId {
get { return _itemEntityId; }
set { _itemEntityId; }
}
....
}
}
You can use the SerializeObject method of JSON.net
string json = JsonConvert.SerializeObject(new OrderModel {
ReferenceNumber = "Testing OAKLAND",
CustomerNotes = "Testing",
DeliveryDate = DateTime.Now,
OrderLineItems = new List<OrderItem>() {
new OrderItem { ItemEntityId = 14771, Quantity = 2 }
}
});
I know this seems like more code, but believe me it will save you a lot of hassle in the future and for any other developers looking at your code.

Categories