SharePoint - Client Object Model - Get Sub Folder Items - sharepoint-2010

each 'listItem' contains items , how to get them? I'm trying for a while but only fail ,
help , thanks
the camlQuery is from some tests and examples from the web , didn't help ( had many changes)
ClientContext clientContext = new ClientContext("http://xxx.xxx.com");
List list = clientContext.Web.Lists.GetById(new Guid("{F91A0F26-2826-4B3B-AF30-ED7DE4494C7B}"));
clientContext.Load(list);
clientContext.ExecuteQuery();
CamlQuery camlQuery = new CamlQuery();
camlQuery.ViewXml = #"<queryOptions><QueryOptions><ViewAttributes Scope='RecursiveAll'/><Folder></Folder></QueryOptions></queryOptions>";
ListItemCollection listItems = list.GetItems(camlQuery);
clientContext.Load(listItems);
clientContext.ExecuteQuery();
foreach (ListItem listItem in listItems)
{
each lisItem has children/items , how to get them?!
}

I have found the answer , thanks for the helpers... :)
Items is my object I created.
to get "folderServerRelativeUrl" value, you can get it from
(string)listItem ["FileRef"] when you go over the folders from above foreach
public Items GetFolderItems(string folderServerRelativeUrl, List list, ClientContext clientContext)
{
try
{
var result = new Items(); <-- my class
var query = new CamlQuery();
query.FolderServerRelativeUrl = folderServerRelativeUrl;
query.ViewXml = "<View Scope=\"RecursiveAll\"> " +
"<Query>" +
"<Where>" +
"<Eq>" +
"<FieldRef Name=\"FileDirRef\" />" +
"<Value Type=\"Text\">" + folderServerRelativeUrl + "</Value>" +
"</Eq>" +
"</Where>" +
"</Query>" +
"</View>";
var folderItems = list.GetItems(query);
clientContext.Load(folderItems);
clientContext.ExecuteQuery();
foreach (ListItem item in folderItems)
{
// item[ "..." ];
}
return result;
}
catch (Exception)
{
return null;
}
}

Another way to get all items of list folders:
camlQuery.ViewXml = #"<View Scope='RecursiveAll'>
<Query>
<Where>
<Eq>
<FieldRef Name='FSObjType' />
<Value Type='int'>0</Value>
</Eq>
</Where>
</Query>
</View>";

Thank you for this great answer. Just to let you know that the folderServerRelativeUrl variable should be from the root Url (except the http://server). I did have a list named "Vendors" inside documentcenter. That is, siteUrl is http://server/documentcenter and the list name is Vendors. I had to pass "/documentcenter/Vendors/..." as my folderServerRelativeUrl. But that is OK. I am still grateful to you.
Stack Overflow folks, it is so sad that I could not add a comment underneath his answer. I had to submit this comment as an answer. Help me if this could be done in a different way. I do not want to edit his answer.
~Sharmin

Related

SharePoint 2010 Custom List and Attachments

I have created Custom List with few columns namely:
Title
Description
HrefLink
And optionally upload Attachments to the list item.
My scenario is as following, fetch the data from the list and print the data in list with hyperlink. Here, for hyperlink I should attach the any attachment is there for an item else pull the HrefLink field value.
How can I find if a list item has an attachment and how can I pull the path of attachment and print it?
I have achived fetching the attachments using the following login and printed to literal:
SPSecurity.RunWithElevatedPrivileges(delegate()
{
using (SPSite currentSite = new SPSite(siteUrl))
{
using (SPWeb currentWeb = currentSite.OpenWeb())
{
/*Footer - Hotspot Links */
//Define string builder to attach the fetched content
StringBuilder strFooterHotspotLinks = new StringBuilder();
SPList lstFooterHotspotLinks = currentWeb.Lists["Footer Hotspot Links"];
//Difine list query
SPQuery spQryFooterHotspotLinks = new SPQuery();
spQryFooterHotspotLinks.Query = "<OrderBy><FieldRef Name='Hotspot_x0020_Order' Ascending='True' /></OrderBy>";
spQryFooterHotspotLinks.RowLimit = 5;
SPListItemCollection lstItmFooterHotspotLinks = lstFooterHotspotLinks.GetItems(spQryFooterHotspotLinks);
int lnkCount = 1;
if (lstItmFooterHotspotLinks.Count > 0)
{
foreach (SPListItem itmFooterHotspotLinks in lstItmFooterHotspotLinks)
{
String qlAttachmentAbsUrl = itmFooterHotspotLinks.Attachments.UrlPrefix; //gets the containing directory URl
SPAttachmentCollection qlAttachments = itmFooterHotspotLinks.Attachments; //check the attachment exists or not for list item
//If list attachmetns are existing
if (qlAttachments.Count > 0)
{
//Loop the list to find the attachments exist ot not and attach to the link
foreach (String qlAttachmentName in qlAttachments)
{
strFooterHotspotLinks.Append("<li><a href='" + qlAttachmentAbsUrl + qlAttachmentName + "'><span class='icn-" + lnkCount + "'></span>" + itmFooterHotspotLinks["Hotspot Title"] + "</a></li>");
lnkCount++;
}
}
else
{
strFooterHotspotLinks.Append("<li><a href='" + itmFooterHotspotLinks["Hotspot Link"] + "'><span class='icn-" + lnkCount + "'></span>" + itmFooterHotspotLinks["Hotspot Title"] + "</a></li>");
lnkCount++;
}
}
}

SharePoint 2010 Wiki Template Script Issue

I'm looking for a way to give my SharePoint users a way to create new wiki pages from an existing template. In the process of researching I found a great walkthrough that seems to fit the need (http://www.mssharepointtips.com/tip.asp?id=1072&page=2), but I'm having trouble getting it to work. The problem seems to lie in the assignment of a path to PATHTOWIKI-- if I use "/Weekly Update Wiki", the script returns an error of "There is no Web named '/Weekly Update Wiki'." If I use "Weekly Update Wiki" without the forward slash, I instead get an error of "There is no Web named '/sites/[parentSite]/[childSite]/Weekly Update Wiki/Weekly Update Wiki'."
Any ideas about what I'm not understanding here?
function myCreateProject() {
// Configure these for your environment
// include no slashes in paths
var PATHTOWIKI = "Weekly Update Wiki";
var PATHTOPAGES = "Pages";
// file name only for template page, no extension
var TEMPLATEFILENAME = "Template";
var myPathToWiki = encodeURIComponent(PATHTOWIKI);
var myPathToPages = PATHTOPAGES + "%2f";
var myTemplateFileName = encodeURIComponent(TEMPLATEFILENAME) + "%2easpx";
var EnteredProject = document.getElementById("NewProjName");
var myNewName = EnteredProject.value;
if(myNewName == "") {
alert('Please enter a name for the new project page');
} else {
myNewName = encodeURIComponent(myNewName) + "%2easpx"
$.ajax({
url: PATHTOWIKI + "/_vti_bin/_vti_aut/author.dll",
data: ( "method=move+document%3a14%2e0%2e0%2e4730&service%5fname="
+ myPathToWiki +
"&oldUrl=" + myPathToPages + myTemplateFileName +
"&newUrl=" + myPathToPages + myNewName +
"&url%5flist=%5b%5d&rename%5foption=nochangeall&put%5foption=edit&docopy=true"
),
success: function(data) {
var rpcmsg1 = getMessage(data, "message=", "<p>");
$("#myInfo").append("<br />" + rpcmsg1);
if(rpcmsg1.indexOf("successfully") < 0) {
// get error info
var rpcmsg2 = getMessage(data, "msg=", "<li>");
$("#myInfo").append("<br />" + rpcmsg2 + "<br />");
} else {
$("#myInfo").append("<br />Go to new page<br />");
}
},
type: "POST",
beforeSend: function(XMLHttpRequest) {
XMLHttpRequest.setRequestHeader("X-Vermeer-Content-Type",
"application/x-www-form-urlencoded");
}
});
}
}
Update: I figured out what needed to happen in my case. Since I couldn't get a grasp on the relative approach, I just went with the absolute path for PATHTOWIKI and slightly modified the append in the ajax call.
PATHTOWIKI:
var PATHTOWIKI = "https://[domain]/sites/[parentSite]/[childSite]";
append:
$("#myInfo").append("<br />Go to new page<br />");
The change in the latter line of code is subtle; since I used an absolute path in PATHTOWIKI, I just removed the leading forward slash in the anchor tag, so that <a href=\"/" became <a href=\"". This renders the script slightly less portable, but since it's a one-off effort I'll stick with this unless anything comes along to expand the scope.

Alternative for EnsureUser in SharePoint client object model

I need to get LookUpId of a user in SharePoint 2010 using client object model. I am able to get it using EnsureUser method, but this method adds the user to the SharePoint web site if the user is not available to the site.My requirement is get the LookupId without adding the user to SharePoint
Is there a alternative way to get the LookupId without using EnsureUser method?
If not, after getting the LookupId using EnsureUser method, can we remove the user from the SharePoint site?
Appreciate your suggestions.
Web.SiteUserInfoList Property gets the UserInfo list of the site collection that contains the Web site.
The following code demonstrates how to get userInfo (including userId property) by userName:
function getUserInfo(userName,Success,Error)
{
var context = new SP.ClientContext.get_current();
var userInfoList = context.get_web().get_siteUserInfoList();
var query = new SP.CamlQuery();
var viewXml = "<View> \
<Query> \
<Where> \
<Eq><FieldRef Name='UserName' /><Value Type='Text'>" + userName + "</Value></Eq> \
</Where> \
</Query> \
<RowLimit>1</RowLimit> \
</View>";
query.set_viewXml(viewXml);
var items = userInfoList.getItems(query);
context.load(items,'Include(Deleted,Department,EMail,FirstName,ID,IsActive,IsSiteAdmin,JobTitle,LastName,MobilePhone,Name,Notes,Office,Picture,SipAddress,UserName,WebSite,WorkPhone)');
context.executeQueryAsync(function(){
if(items.get_count() > 0) {
var item = items.itemAt(0);
Success(item.get_fieldValues());
}
else {
Success(null);
}
},
Error
);
}
//Usage
getUserInfo('username#tenant.onmicrosoft.com',function(userInfo){
console.log('User Id: ' + userInfo.ID);
},
function(sender,args){
console.log(args.get_message());
});

fetch gmail calendar events in mvc 4 application

I am working on mvc 4 web application. I want to implement a functionality wherein the scenario is as follows-
There will be gmail id as input for ex: abc#gmail.com. When user will enter this, application should fetch all the calendar events of that respective email id and display them.
I have gone through this-
http://msdn.microsoft.com/en-us/library/live/hh826523.aspx#cal_rest
https://developers.google.com/google-apps/calendar/v2/developers_guide_protocol
I am new to this and i have searched a lot but not got any solution. Please help! Thanks in advance!
Got the solution . Just refer this.
https://github.com/nanovazquez/google-calendar-sample
Please check the steps below.
Add Google Data API SDK.
Try this code.. I wrote this code for one project but I removed some codes that are not related to Google Calender. If you don't want to use SDK, you can simply do http-get or http-post to your calender link based on spec.
CalendarService service = new CalendarService("A.Name");
const string GOOGLE_CALENDAR_FEED = "https://www.google.com/calendar/feeds/";
const string GOOGLE_CALENDAR_DEFAULT_ALL_CALENDAR_FULL = "default/allcalendars/full";
const string GOOGLE_CALENDAR_ALL_PRIVATE_FULL = "private/full";
private void SetUserCredentials() {
var userName = ConfigurationManager.AppSettings["GoogleUserName"];
var passWord = Security.DecryptString(ConfigurationManager.AppSettings["GooglePasswrod"]).ToInsecureString();
if (userName != null && userName.Length > 0) {
service.setUserCredentials(userName, passWord);
}
}
private CalendarFeed GetCalendarsFeed() {
CalendarQuery calendarQuery = new CalendarQuery();
calendarQuery.Uri = new Uri(GOOGLE_CALENDAR_FEED + GOOGLE_CALENDAR_DEFAULT_ALL_CALENDAR_FULL);
CalendarFeed resultFeed = (CalendarFeed)service.Query(calendarQuery);
return resultFeed;
}
private TherapistTimeSlots GetTimeSlots(CalendarEntry entry2) {
string feedstring = entry2.Id.AbsoluteUri.Substring(63);
var postUristring = string.Format("{0}{1}/{2}", GOOGLE_CALENDAR_FEED, feedstring, GOOGLE_CALENDAR_ALL_PRIVATE_FULL);
EventFeed eventFeed = GetEventFeed(postUristring);
slot.Events = new List<Event>();
if (eventFeed != null) {
var orderEventList = (from entity in eventFeed.Entries
from timeslot in ((EventEntry)entity).Times
orderby timeslot.StartTime
select entity).ToList();
}
return slot;
}
private EventFeed GetEventFeed(string postUristring) {
var eventQuery = new EventQuery();
eventQuery.Uri = new Uri(postUristring);
var h = Convert.ToInt32(DateTime.Now.ToString("HH", System.Globalization.DateTimeFormatInfo.InvariantInfo));
eventQuery.StartTime = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, h, 0, 0);
eventQuery.EndTime = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, h + 2, 0, 0);
try {
EventFeed eventFeed = service.Query(eventQuery) as EventFeed;
return eventFeed;
}
catch (Exception ex) {
/*
* http://groups.google.com/group/google-calendar-help-dataapi/browse_thread/thread/1c1309d9e6bd9be7
*
* Unfortunately, the calendar API will always issue a redirect to give you a
gsessionid that will optimize your subsequent requests on our servers.
Using the GData client library should be transparent for you as it is taking
care of handling those redirect; but there might some times where this error
occurs as you may have noticed.
The best way to work around this is to catche the Exception and re-send the
request as there is nothing else you can do on your part.
*/
return null;
}
}

Approve a SharePoint workflow task using SharePoint Web Services / Object Model

I have created a workflow is SharePoint Designer and associated it with a list. The workflow creates an approval process, so SharePoint creates a task in the Tasks list so that the user can approve or reject.
What I need to do is to approve or reject the task without opening the task in the task list. After some research I figured that I can use SharePoint Web Services. However I feel lost as I don't know which service, e.g. Lists.asmx, and which method, e.g. UpdateListItems, to call.
Can someone guide me through the following:
1- Is it feasible to approve a workflow task SharePoint Web Services?
2- Can you show me an example of how to approve a task, e.g. which service and method to call and what should be the parameters?
Update
I have been using the following XML to set the workflow to complete:
batchElement.InnerXml = "<Method ID='1' Cmd='Update'>" // Also used Moderate
+ "<Field Name='ID'>115</Field>"
+ "<Field Name='Status'>Completed</Field>"
+ "<Field Name='FormData'>Completed</Field>" // Also used Approved
+ "<Field Name='WorkflowOutcome'>Approved</Field>"
+ "<Field Name='Completed'>True</Field>"
+ "<Field Name='PercentComplete'>1</Field>"
+ "<Field Name='_ModerationStatus'>0</Field>"
+ "</Method>";
The task list item is updated but the WorkflowOutcome remains empty and the workflow doesn't move to the next step.
What else I am missing?
Update #2
I am suspecting the ExtendedProperties of the task list item. For an item that was completed using the UI, the ExtendedProperties shows ws_TaskStatus='Approved'. However for an item that was approved using the code ws_TaskStatus doesn't exist.
Update #3
From an MSDN post, I was told to use the Workflow.asmx instead of the Lists.asmx.
I have used the following code:
WorkflowService.Workflow listProxy = new WorkflowService.Workflow();
listProxy.Url = "http://<server_name>/_vti_bin/workflow.asmx";
listProxy.UseDefaultCredentials = true;
int todoID = 118;
Guid tasklistID = new Guid("{79ABFDE7-0398-4AD7-918A-0D40204E7726}");
string itemURL = "http://<server_name>/TestLibrary/volshext.log";
XmlDocument taskData = new XmlDocument();
taskData.Load(#"..\..\TaskData.xml");
try
{
XmlNode response = listProxy.AlterToDo(itemURL, todoID, tasklistID, taskData.DocumentElement);
Console.WriteLine(response.InnerText);
}
The XML I am using to approve the task is
<my:myFields xmlns:my="http://schemas.microsoft.com/office/infopath/2003/myXSD" >
<my:TaskStatus>#</my:TaskStatus>
<my:Comments />
<my:DelegateTo />
<my:NewDescription>Please approve Workflow Demo</my:NewDescription>
<my:NewDueDate />
<my:RequestTo />
<my:Decline>0</my:Decline>
<my:dcr>0</my:dcr>
<my:Status>Completed</my:Status>
</my:myFields>
But again the task was updated but the workflow didn't move forward.
Update #4
I have made one last trial with SharePoint server object model however, again, the task is updated but the workflow is not moving forward.
Here is my code:SPSite site = new SPSite("http://sitenamehere/");
using (SPWeb web = site.OpenWeb())
{
SPList list = web.Lists["Shared Documents"];
//SPListItem item = list.GetItemById(18);
SPListItem item = list.GetItemByUniqueId(new Guid("5300d16e-94f8-4338-8206-4a57ab7c369b"));
SPWorkflow workflow = item.Workflows[0];
SPWorkflowTask task = workflow.Tasks[0];
Hashtable ht = new Hashtable();
ht[SPBuiltInFieldId.Completed] = "TRUE";
ht["Completed"] = "TRUE";
ht[SPBuiltInFieldId.PercentComplete] = 1.0f;
ht["PercentComplete"] = 1.0f;
ht["Status"] = "Completed";
ht[SPBuiltInFieldId.TaskStatus] = SPResource.GetString(new CultureInfo((int)task.Web.Language, false), Strings.WorkflowStatusCompleted, new object[0]);
//ht["TaskStatus"] = "#";
//ht["ows_TaskStatus"] = "Approved";
//ht["FormData"] = SPWorkflowStatus.Completed;
//ht["Outcome"] = "Approved";
//task.ModerationInformation.Status = SPModerationStatusType.Approved;
web.AllowUnsafeUpdates = true;
SPWorkflowTask.AlterTask((task as SPListItem), ht, true);
}
After a lot of trials and investigation I just had the following code working to approve the task
SPSite site = new SPSite("http://servername/");
using (SPWeb web = site.OpenWeb())
{
SPList list = web.Lists["TestList"];
SPListItem item = list.GetItemById(22);
SPWorkflow workflow = item.Workflows[0];
SPWorkflowTask task = workflow.Tasks[0];
Hashtable ht = new Hashtable();
ht[SPBuiltInFieldId.Completed] = "TRUE";
ht["Completed"] = "TRUE";
ht[SPBuiltInFieldId.PercentComplete] = 1.0f;
ht["PercentComplete"] = 1.0f;
ht["Status"] = "Completed";
ht[SPBuiltInFieldId.TaskStatus] = SPResource.GetString(new CultureInfo((int)task.Web.Language, false), Strings.WorkflowStatusCompleted, new object[0]);
ht[SPBuiltInFieldId.WorkflowOutcome] = "Approved";
ht["TaskStatus"] = "Approved";
ht["FormData"] = SPWorkflowStatus.Completed;
web.AllowUnsafeUpdates = true;
SPWorkflowTask.AlterTask((task as SPListItem), ht, true);
}
I suspect that ht["TaskStatus"] = "Approved"; is that attribute that solved it. Anyway I will try to narrow on the set of properties that need to be changed.
You can use the following code that uses the lists web service and the UpdateListItems method. The key is to use the Cmd='Moderate'
public static XmlNode UpdateListItemApprove()
{
listservice.Lists listProxy = new listservice.Lists();
string xml = "<Batch OnError='Continue'><Method ID='1' Cmd='Moderate'><Field Name='ID'/><Field Name='FileRef'>http://basesmcdev2/sites/tester1/approvals/KL022030.lic</Field><Field Name=\"_ModerationStatus\" >0</Field></Method></Batch>";
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
XmlNode batchNode = doc.SelectSingleNode("//Batch");
listProxy.Url = "http://basesmcdev2/sites/tester1/_vti_bin/lists.asmx";
listProxy.UseDefaultCredentials = true;
XmlNode resultNode = listProxy.UpdateListItems("approvals", batchNode);
return resultNode;
}
I'm not sure if Madhur's solution works on the associated item or on the task, but to update the task try:
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<UpdateListItems
xmlns="http://schemas.microsoft.com/sharepoint/soap/">
<listName>Tasks</listName>
<updates>
<Batch OnError="Continue" ListVersion="1">
<Method ID="1" Cmd="Update">
<Field Name="ID">199</Field>
<Field Name="Outcome">Approved</Field>
<Field Name="Status">Completed</Field>
<Field Name="ows_TaskStatus">Approved</Field>
</Method>
</Batch>
</updates>
</UpdateListItems>
</soap:Body>
</soap:Envelope>
Info on the service:
http://objectmix.com/sharepoint/800144-updatelistitems-web-service-does-not-update-field.html
Info on the approved field:
http://social.msdn.microsoft.com/Forums/en/sharepointworkflow/thread/6712d379-2df6-4223-9a29-b2e60493f1b6
http://social.msdn.microsoft.com/Forums/en/sharepointworkflow/thread/3dc95190-cc61-4067-ac35-2d1a82fad499