Reputation: 1416
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
Upvotes: 1
Views: 1892
Reputation: 1416
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();
Upvotes: 0
Reputation: 59318
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.
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; }
}
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);
Upvotes: 1