I'm trying to update SPFile properties.
Here is my code:
using (SPSite oSite = new SPSite(sFileURL))
{
using (SPWeb oWeb = oSite.OpenWeb())
{
oWeb.AllowUnsafeUpdates = true;
oFile = oWeb.GetFile(sFileURL);
foreach (XmlNode xNode in oXmlDoc.FirstChild.ChildNodes)
{
oFile.Item.Properties[xNode.Name] = xNode.InnerText;
string itemmm =oFile.Item.Properties[xNode.Name].ToString();
}
oFile.Update();
oWeb.AllowUnsafeUpdates = false;
}
}
The problem is that when I check the file properties in SharePoint I don't see the changes I have made.
I was trying to add AllowUnsafeUpdates = true but it didn't solve the problem.
What else can I do?
In fact, you don't modify SPFile instance, but the associated SPItem. Hence calling SPFile.Update() does nothing. It's better to work with the SPItem instance directly:
SPItem item = oFile.Item;
item.Properties[xNode.Name] = xNode.InnerText;
item.Update();
Also, AllowUnsafeUpdates property is not relevant to your situation. Do not alter it.
Your code is lacking all checks which is to be done before actual update.
using (SPSite oSite = new SPSite(sFileURL))
{
using (SPWeb oWeb = oSite.OpenWeb())
{
oWeb.AllowUnsafeUpdates = true;
SPFile oFile = oWeb.GetFile(sFileURL);
if (oFile == null)
{
return false;
}
SPListItem item = oFile.GetListItem();
if (item.File.Level == SPFileLevel.Checkout)
{
item.File.UndoCheckOut();
}
if (item.File.Level != SPFileLevel.Checkout)
{
item.File.CheckOut();
}
item["Your Column name"] = "Value";
item.SystemUpdate(false);
item.File.CheckIn("SystemCheckedin");
item.File.Publish("SystemPublished");
oWeb.AllowUnsafeUpdates = false;
}
}
Related
I have implemented an SSIS Package getting all appoinments from a particular shared outlook calendar.
What I noticed is that the recurring ones are NOT returned because they are a kind of virtual. Only the Master of them will give me the ability to get also the recurring ones.
Looking at my code, do you have any suggestions how I can retrieve also the recurring ones?
I'm just a little stuck and any hint is highly appreciated!
#region Namespaces
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Data;
using Microsoft.SqlServer.Dts.Pipeline.Wrapper;
using Microsoft.SqlServer.Dts.Runtime.Wrapper;
using Microsoft.Exchange.WebServices.Data;
#endregion
[Microsoft.SqlServer.Dts.Pipeline.SSISScriptComponentEntryPointAttribute]
public class ScriptMain : UserComponent
{
string sharedCalendarID;
static FolderId FindPublicFolder(ExchangeService myService, FolderId baseFolderId, string folderName)
{
// search using paging.
FolderView folderView = new FolderView(10, 0);
folderView.OffsetBasePoint = OffsetBasePoint.Beginning;
// need only DisplayName and Id of every folder
// reduce the property set to the properties
folderView.PropertySet = new PropertySet(FolderSchema.DisplayName, FolderSchema.Id);
FindFoldersResults folderResults;
do
{
folderResults = myService.FindFolders(baseFolderId, folderView);
foreach (Folder folder in folderResults)
if (String.Compare(folder.DisplayName, folderName, StringComparison.OrdinalIgnoreCase) == 0)
return folder.Id;
if (folderResults.NextPageOffset.HasValue)
// go to the next page
folderView.Offset = folderResults.NextPageOffset.Value;
}
while (folderResults.MoreAvailable);
return null;
}
public override void CreateNewOutputRows()
{
// IMPORTANT: ExchangeService is NOT thread safe, so one should create an instance of
// ExchangeService whenever one needs it.
ExchangeService myService = new ExchangeService(ExchangeVersion.Exchange2013_SP1);
myService.Credentials = new NetworkCredential("username", "password");
myService.Url = new Uri("https://......Exchange.asmx");
// next line is very practical during development phase or for debugging
myService.TraceEnabled = true;
Folder myPublicFoldersRoot = Folder.Bind(myService, WellKnownFolderName.PublicFoldersRoot);
string myPublicFolderPath = #"CHI\WIED PFL Agenda";
string[] folderPath = myPublicFolderPath.Split('\\');
FolderId fId = myPublicFoldersRoot.Id;
foreach (string subFolderName in folderPath)
{
fId = FindPublicFolder(myService, fId, subFolderName);
if (fId == null)
{
// No Calendar found
return;
}
}
// verify
Folder folderFound = Folder.Bind(myService, fId);
if (String.Compare(folderFound.FolderClass, "IPF.Appointment", StringComparison.Ordinal) == 0)
{
sharedCalendarID = fId.ToString(); ;
}
else
return;
CalendarFolder myPublicFolder = CalendarFolder.Bind(myService,
//WellKnownFolderName.Calendar,
fId,
PropertySet.FirstClassProperties);
// search using paging. page size 10
ItemView viewCalendar = new ItemView(10);
// include all properties which we need in the view
// comment the next line then ALL properties will be read from the server.
//viewCalendar.PropertySet = new PropertySet(ItemSchema.Subject, ItemSchema.Id);
viewCalendar.Offset = 0;
viewCalendar.OffsetBasePoint = OffsetBasePoint.Beginning;
viewCalendar.OrderBy.Add(ContactSchema.DateTimeCreated, SortDirection.Descending);
FindItemsResults<Item> findResultsCalendar;
do
{
//SearchFilter searchFilter = new SearchFilter.IsGreaterThan(AppointmentSchema.Start, DateTime.Today);
var searchFilter = new SearchFilter.SearchFilterCollection(LogicalOperator.And,
new SearchFilter.IsEqualTo(ItemSchema.ItemClass, "IPM.Appointment"),
new SearchFilter.IsGreaterThanOrEqualTo(AppointmentSchema.Start, DateTime.Now),
new SearchFilter.IsLessThan(AppointmentSchema.Start, DateTime.Now.AddDays(4)));
findResultsCalendar = myPublicFolder.FindItems(searchFilter, viewCalendar);
//get additional properties for each item returned by view, do this as view cannot return a lot of useful stuff like attendees
ServiceResponseCollection<ServiceResponse> addProperties =
myService.LoadPropertiesForItems(from Item item in findResultsCalendar select item,
new PropertySet(
BasePropertySet.IdOnly,
AppointmentSchema.Body,
AppointmentSchema.Subject,
AppointmentSchema.Start,
AppointmentSchema.End,
AppointmentSchema.IsRecurring,
AppointmentSchema.AppointmentType
));
List<Appointment> additionalProperties = new List<Appointment>(addProperties.Count);
if (addProperties != null)
{
foreach (ServiceResponse currentResponce in addProperties)
{
additionalProperties.Add(((Appointment)((GetItemResponse)currentResponce).Item));
}
}
foreach (Item item in findResultsCalendar)
{
Appointment appt = item as Appointment;
if (item is Appointment || appt.AppointmentType == AppointmentType.RecurringMaster)
{
Appointment currentAppointmentAddProps = null;
currentAppointmentAddProps = additionalProperties.Find(
delegate(Appointment arg)
{
return arg.Id == item.Id;
}
);
//convert to int wether the Appointment is recurring or not
int isRecurring = currentAppointmentAddProps.IsRecurring ? 1 : 0;
Appointment appoint = item as Appointment;
OutputRecordSetBuffer.AddRow();
OutputRecordSetBuffer.ActualEndDate = currentAppointmentAddProps.End;
OutputRecordSetBuffer.ActualStartDate = currentAppointmentAddProps.Start;
OutputRecordSetBuffer.Subject = appoint.Subject;
OutputRecordSetBuffer.EntryID = Guid.NewGuid();
//OutputRecordSetBuffer.Detail = appoint.Body.ToString();
//OutputRecordSetBuffer.CalendarID = fId.ToString();
//OutputRecordSetBuffer.AppointmentID = appoint.Id.ToString();
OutputRecordSetBuffer.CalendarID = sharedCalendarID;
OutputRecordSetBuffer.AppointmentID = Guid.NewGuid();
OutputRecordSetBuffer.IsRecurring = isRecurring;
}
}
if (findResultsCalendar.NextPageOffset.HasValue)
// go to the next page
viewCalendar.Offset = findResultsCalendar.NextPageOffset.Value;
}
while (findResultsCalendar.MoreAvailable);
}
}
I have solved my issue on my own :)
Instead of using the ItemView class, I used the CalendarView class.
CalendarView expands also the recurring appointments, thats it :)
At work we had to move from SharePoint 2010 to 2013 and my code for retrieving list items doesn't work anymore. Here is my code for SP 2010:
com.mycompany.intranet.Lists listService = new com.mycompany.intranet.Lists();
listService.Credentials = System.Net.CredentialCache.DefaultCredentials;
listService.Url = "url";
System.Xml.XmlDocument xmlDoc = new System.Xml.XmlDocument();
string listName = cbxMailDistributionList.SelectedValue.ToString();
string viewName = "";
string rowLimit = "0";
System.Xml.XmlElement query = xmlDoc.CreateElement("Query");
System.Xml.XmlElement viewFields = xmlDoc.CreateElement("ViewFields");
System.Xml.XmlElement queryOptions = xmlDoc.CreateElement("QueryOptions");
viewFields.InnerXml = "<FieldRef Name='Title' />";
System.Xml.XmlNode nodeListItems =
listService.GetListItems(listName, viewName, query, viewFields, rowLimit, queryOptions, null);
xmlDoc.LoadXml(nodeListItems.InnerXml);
xlNodeList rows = xmlDoc.GetElementsByTagName("z:row");
List<string> recipients = new List<string>();
foreach (XmlNode attribute in rows)
{
if(attribute.Attributes["ows_Title"].Value == null){}
else {
if (recipients.Contains(attribute.Attributes["ows_Title"].Value)){}
else {
recipients.Add(attribute.Attributes["ows_Title"].Value);
}
}
}
recipients.Sort();
distributionList = recipients;
Can you please help me to get it working with a SharePoint 2013 list again?
URL has already been updated but i get the following error: https://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=DE-DE&k=k(EHNullReference);k(TargetFrameworkMoniker-.NETFramework,Version%3Dv4.0);k(DevLang-csharp)&rd=true
But the list has no empty fields.
listName
is the ID of the list element.
Please help.
Thanks in advance!
Finally it works again with this code:
List<string> recipients = new List<string>();
string siteURL = #"myurl/";
ClientContext cc = new ClientContext(siteURL);
cc.Credentials = System.Net.CredentialCache.DefaultCredentials;
Web web = cc.Web;
List list = web.Lists.GetById(new Guid(cbxMailDistributionList.SelectedValue.ToString()));
CamlQuery caml = new CamlQuery();
ListItemCollection items = list.GetItems(caml);
cc.Load<List>(list);
cc.Load<ListItemCollection>(items);
cc.ExecuteQuery();
foreach (Microsoft.SharePoint.Client.ListItem item in items)
{
if(item.FieldValues["Title"] == null) { }
else
{
if (recipients.Contains(item.FieldValues["Title"].ToString())) { }
else
{
recipients.Add(item.FieldValues["Title"].ToString());
}
}
}
recipients.Sort();
distributionList = recipients;
}
else
{
distributionList = null;
}
New day, new luck. Sorry for the prematurely posting of this question. I should have slept on it for a night. ;)
BR
How to get fields values from a particular list item.In my case i want to get all form fileds of Workplan list.Actually i want to get Workplan all list item and insert to sharepoint 2013 associated database.
I try the following code.
string strUrl = "http://example.com/default.aspx";
using (SPSite site = new SPSite(strUrl))
{
using (SPWeb web = site.OpenWeb())
{
SPList list = web.Lists[52];
SPQuery myquery = new SPQuery();
myquery.Query = "";
SPListItemCollection items = list.GetItems(myquery);
foreach (SPListItem item in items)
{
if (item != null)
{
var Name = item.ListItems.Fields.List;
Console.WriteLine("Name is :" + Name);
}
}
}
}
This is the easiest way I can think of using Server Object Model:
string strUrl = "http://example.com";
using(SPSite oSite = new SPSite(strUrl))
{
using(SPWeb oWeb = oSite.OpenWeb())
{
SPList list = oWeb.Lists["Workplan"];
foreach(SPField field in list.Fields)
{
Console.WriteLine(field.Title);
}
}
}
Btw, as for your site-URL "http://example.com/default.aspx" it is enough to do it like "http://example.com".
For more information on Sharepoint I recommend using this site in the future.
using (SPSite site = new SPSite("URL")
{
using (SPWeb web = site.OpenWeb("sitecollection/subsite"))
{
//to get specific list type
string listUrl = "/sites/sitecollection/subsite/Lists/Announcements";
SPList list = web.GetList(listUrl);
Console.WriteLine("List URL: {0}", list.RootFolder.ServerRelativeUrl);
}
}
//To get all lists from spweb use this:
SPSite oSiteCollection = SPContext.Current.Site;
using(SPWebCollection collWebs = oSiteCollection.AllWebs)
{
foreach (SPWeb oWebsite in collWebs)
{
SPListCollection collSiteLists = oWebsite.Lists;
foreach (SPList oList in collSiteLists)
{
//get your each list here
}
oWebsite.Dispose();
}
}
Essentially what I'm trying to do is add a computer/user to a group. After I add the object to the group, I want to query the groups of the object to see what they have.
It seems that the GetGroups method doesn't update fast enough. My test always seems to fail. If I put some breakpoints in VS, it will run if I wait enough.
I'm new to playing with the AccounManagement namespace (I've used the pre .net 3.5 code alot). I guess I could loop through the code a few times but I'm seeing if other people have suggestions for this.
I've done the following unit test
[Test]
public void Check()
{
string distinguishedName = "ComputerDistinguishedName";
string groupDN = "GroupDistinguished name";
// Remove the identity from the group so it does crashes if it's already part of it.
GroupCtrl.RemoveIdentityFromGroup(groupDN, distinguishedName);
using (var ctx = new PrincipalContext(ContextType.Domain))
{
var group = GroupPrincipal.FindByIdentity(ctx, groupDN);
Console.WriteLine(group.Members.Count);
if (!group.Members.Contains(ctx, IdentityType.DistinguishedName, distinguishedName))
{
group.Members.Add(ctx, IdentityType.DistinguishedName, distinguishedName);
group.Save();
}
foreach (var item in group.Members)
{
Console.WriteLine(item.DistinguishedName);
}
Console.WriteLine(group.Members.Count);
}
var isMemberOf = false;
using (PrincipalContext ctx = new PrincipalContext(ContextType.Domain))
{
var found = Principal.FindByIdentity(ctx, IdentityType.DistinguishedName, distinguishedName);
if (found != null)
{
Console.WriteLine(found.DistinguishedName);
foreach (var item in found.GetGroups())
{
Console.WriteLine(item.DistinguishedName);
if (item.DistinguishedName == groupDN)
{
isMemberOf = true;
}
}
}
Assert.AreEqual(true, isMemberOf);
}
// Reset our group membership to run the test again.
GroupCtrl.RemoveIdentityFromGroup(groupDN, distinguishedName);
}
Edit 1:
So I tried two different approaches
1 -
I tried getting the getUnderlyingObject and then looping through the memberOf properties (same result)
2 -
I avoided the AccountManagement code and used a DirectorySearcher and looped through the memberOf property and it comes up every time. Sighh
So I changed my code to the following. The old way of checking memberOf with DirectorySearch works everytime. I was hoping to use only use the AccountManagement class for this project. I wonder if future version of the class will be better.
[Test]
public void Check()
{
//var test = new Constructor();
var test = new AdContextObject();
string distinguishedName = "ComputerDistinguishedName";
string groupDN = "GroupDistinguished name";
// Remove the identity from the group so it does crashes if it's already part of it.
GroupCtrl.RemoveIdentityFromGroup(groupDN, distinguishedName);
using (var ctx = test.GetContext())
{
var group = GroupPrincipal.FindByIdentity(ctx, groupDN);
Console.WriteLine(group.Members.Count);
if (!group.Members.Contains(ctx, IdentityType.DistinguishedName, distinguishedName))
{
Console.WriteLine("addGroup");
group.Members.Add(ctx, IdentityType.DistinguishedName, distinguishedName);
group.Save();
}
foreach (var item in group.Members)
{
Console.WriteLine(item.DistinguishedName);
}
Console.WriteLine(group.Members.Count);
}
DirectoryEntry de = new DirectoryEntry();
de.Path = "LdapSource";
DirectorySearcher ser = new DirectorySearcher(de);
ser.Filter = "(&(ObjectCategory=computer)(name=ComputerName))";
ser.PropertiesToLoad.Add("name");
ser.PropertiesToLoad.Add("memberOf");
var returnValue = ser.FindAll();
var isMemberOf = false;
foreach (SearchResult res in returnValue)
{
var memberOf = GetMultiValue(res, "MemberOf");
foreach (var item in memberOf)
{
Console.WriteLine(item);
if (item.Equals(groupDN, StringComparison.OrdinalIgnoreCase))
{
isMemberOf = true;
}
}
}
Assert.AreEqual(true, isMemberOf);
Console.WriteLine("old way worked fine");
isMemberOf = false;
using (PrincipalContext ctx = test.GetContext())
{
var found = Principal.FindByIdentity(ctx, IdentityType.DistinguishedName, distinguishedName);
if (found != null)
{
foreach (var item in found.GetGroups())
{
Console.WriteLine(item.DistinguishedName);
if (item.DistinguishedName.Equals(groupDN, StringComparison.OrdinalIgnoreCase))
{
isMemberOf = true;
}
}
}
Assert.AreEqual(true, isMemberOf);
}
// Reset our group membership to run the test again.
GroupCtrl.RemoveIdentityFromGroup(groupDN, distinguishedName);
}
public static string[] GetMultiValue(SearchResult result, string fieldName)
{
string[] returnValue = null;
if (result != null)
{
if (result.Properties.Contains(fieldName))
{
ResultPropertyValueCollection propertyValue = result.Properties[fieldName];
if (propertyValue != null)
{
if (propertyValue.Count > 1)
{
string[] valueArray = new string[propertyValue.Count];
for (int i = 0; i < propertyValue.Count; i++)
{
string valStr = propertyValue[i].ToString();
valueArray[i] = valStr;
}
returnValue = valueArray;
}
else if (propertyValue.Count == 1)
{
string[] tempString = new string[] { propertyValue[0].ToString() };
returnValue = tempString;
}
else
{
string[] tempString = new string[] { };
returnValue = tempString;
}
}
}
}
return returnValue;
}
public class AdContextObject
{
public PrincipalContext GetContext()
{
return new PrincipalContext(ContextType.Domain, "domainStuff", "MoreDomainStuff");
}
}
I have some code to bind SharePoint list items to text boxes. But I only got the code to bind one item. My list contains two columns (ID and Name):
*ID Name*
1 Steven
2 Joe
3 Henry
This code picks out the Name field from the first item (that means my textbox will show "Steven":
try
{
SPQuery query = new SPQuery();
query.Query = "";
query.ViewFields = "";
query.RowLimit = 100;
using (SPSite site = new SPSite(SPContext.Current.Web.Url))
{
using (SPWeb web = site.OpenWeb())
{
SPList list = web.Lists.TryGetList("Employee List");
if (list != null)
{
if (list.GetItems(query).GetDataTable() != null)
{
DataTableReader rdr = list.GetItems(query).GetDataTable().CreateDataReader();
if (rdr.Read())
{
TextBox1.Text = rdr["Name"].ToString();
rdr.Close();
}
}
}
}
}
}
How to select the rest of them names? I was thinking about an if-statement to check if field = ID (1, 2, 3) etc. but couldn't find out anything.
Use a while loop and it should loop through all the "Name" values.
if (list.GetItems(query).GetDataTable() != null)
{
using (DataTableReader rdr = list.GetItems(query).GetDataTable().CreateDataReader())
{
while (rdr.Read())
{
TextBox1.Text = rdr["Name"].ToString();
}
}
}
Addtionally you should be using a using statement to ensure that Dispose() and Close() are both called on the DataTableReader.