Update multiple fields in SharePoint programmatically - c#

I'm trying to update some properties on multiple fields (with the same name) in SharePoint.
I've tried this:
var site = this.Site.RootWeb;
var fields = site.Fields;
foreach (SPField field in fields)
{
if (field.Group.Contains("My Custom Columns"))
{
if (field.Title.Contains("Custom field"))
{
if (field.DefaultValue != null) {
field.DefaultValue = null;
field.Update(true);
}
}
}
}
It updates the first column with the name "Custom field", but after it's giving me this error:
Collection was modified; enumeration operation may not execute.
at Microsoft.SharePoint.SPBaseCollection.SPEnumerator.System.Collections.IEnumerator.MoveNext()
Is it not possible to Update the object in a foreach loop?

This error occurs since you are trying to modify a field collection while iterating it.
The solution would be to replace the line:
foreach (SPField field in fields)
with
foreach (var field in fields.Cast<SPField>().ToList())

The problem I believe is with your
foreach (SPField field in fields)
line of code. You are essentially modifying the collection that you are looping over.
What I would suggest you try is looping and getting the ID's of all the fields in to a
List<GUID>
Then do a foreach statement on this collection getting each field and updating it's value.
List<Guid> guidsList = new List<guid>();
foreach (SPField field in fields)
{
if (field.Group.Contains("My Custom Columns"))
{
if (field.Title.Contains("Custom field"))
{
guidsList.add(field.id)
}
}
}
foreach(Guid currentFieldId in guidsList){
//Get your field
//Update what needs to be updated
}
Many Thanks
Truez

Related

Issue with removing records in EF

I have a list of organizations attached to the users that need to be removed and a new set added. I am using entity framework
var user = db.Users.Find(model.Id);
foreach (var item in user.Organizations)
{
user.Organizations.Remove(item);
}
var userOrgs = db.Organizations.Where(o => model.Organizations.Contains(o.ID)).ToList();
foreach (var item in userOrgs)
{
user.Organizations.Add(item);
}
db.SaveChanges();
I end up getting an exception {"Collection was modified; enumeration operation may not execute."} when i try to remove the second item. Is there an alternate approach?
Try to use ToList in your first foreach:
var user = db.Users.Find(model.Id);
foreach (var item in user.Organizations.ToList())
{
user.Organizations.Remove(item);
}

Insert Multiple Rows to Database LINQ

I have a foreach loop that iterates through a list of type List<NewItem>, creates a new instance of NewItem, sets its properties, then Add()s the item to the context to be inserted upon the execution of SaveChanges():
foreach (var newItem in newItems)
{
NewItem item = new NewItem
{
User = newItem.User,
Itemno = newItem.Itemno
};
db.NewItem.Add(item);
}
try
{
db.SaveChanges();
}
catch (Exception e)
{
Console.WriteLine(e);
}
I am getting the error:
Unable to update the EntitySet 'NewItem' because it has a
DefiningQuery and no element exists in the element to support the
current operation.
Why isn't the Add() method actually adding anything to my db context?
If the target database table doesn't have a primary key, add one.

Adding an option to choicebox in SharePoint, c#

I want to add an option to choicebox named 'yyy' in all lists called 'xxx'. My code prints chosen option from choicebox for every list (I guess so).
I was trying to do field.GetFieldValueAsText(???) on my 'yyy' field (in other words my choicebox) but I don't know what should I pass as an argument to that method.
Anyone has any idea how to solve this out?
Thanks in advance.
SPSite mainSite = new SPSite(path);
SPWebCollection webColl = mainSite.AllWebs;
foreach (SPWeb web in webColl)
{
SPListCollection listColl = web.Lists;
foreach (SPList list in listColl)
{
if (list.Title.Equals("xxx", StringComparison.CurrentCultureIgnoreCase))
{
SPFieldCollection fields = list.Fields;
foreach (SPField field in fields)
{
if (field.Title.Equals("yyy", StringComparison.CurrentCultureIgnoreCase))
{
foreach (SPItem item in items)
Console.WriteLine(item["yyy"]);
}
}
}
}
}

Return entire collection from MongoDB

using the official mongo / c# drivers - what is the best way of returning an entire collection, and what is the best way of storing the data? I've seen some examples of iterating over a collection and returning a particular value, like this:
var collection = db.getCollection("users").findAll();
foreach (var value in collection){
value = collection["key"];
...
}
but what if I don't know the key names - and I just want to return the collection?
You dont need to know the key names when returning a collection.
public static void ReadCollectionDataUsingBson(string collectionName, string databaseName)
{
MongoDatabase database = CreateDatabase(databaseName);
MongoCollection<BsonDocument> collection = database.GetCollection<BsonDocument>(collectionName);
foreach (BsonDocument document in collection.FindAll())
{
foreach (string name in document.Names)
{
BsonElement element = document.GetElement(name);
Console.WriteLine("{0}: {1}", name, element.Value);
}
Console.WriteLine();
}
}
Note: CreateDatabase() function is user defined, so i have just shown you the required code over here.

Retrieve metadata column fields

I need to programmatically retrieve the columns in a Sharepoint document library, in order to set file properties externally to Sharepoint.
I've found that setting the metadata property is not hard as long as you already know the name of the column, which I cannot expect users to input themselves.
As it does not seem possible to do this through the Sharepoint Web Services I have created my own custom web service so I have access to the Client Object Model.
Using this code I am able to retrieve the custom columns I have created, however I am not able to distinguish between the ones editable in the item properties section (picture above) and those which aren't.
SPList list = web.Lists[specificList];
foreach (SPField field in list.Fields)
{
if (!field.Hidden)
{
var title = field.Title;
var description = field.Description;
var parentList = field.ParentList;
var references = field.FieldReferences; // contains names of fields referenced in computed fields
if (references != null)
{
foreach (string reference in references)
{
var test = parentList.Fields.GetField(reference);
}
}
}
}
I get extra properties such as:
Copy Source
Content Type
Checked Out To
Checked In Comment
Type
File
Size
Edit
Version
Source Version
Source Name
I have also tried retrieving the column fields from the SPFolder item, but again this returns many extra properties and is even less filterable.
foreach (SPListItem folderItem in list.Folders)
{
SPFolder folder = folderItem.Folder;
System.Collections.Hashtable oHashtable = folder.Properties;
System.Collections.ICollection collKeys = oHashtable.Keys;
foreach (var key in collKeys)
{
string keyName = key.ToString();
}
}
Is there a standard way to retrieve the column fields I need? Or will I have to manually exclude the defaults ones such as "Checked out to"?
First you have to know which form you are viewing. Is it the EditForm or NewForm?
You can filter the columns visible on a specific form by getting the fields of the ContentType and then check if they are getting displayed on the NewForm (or whatever form):
SPList list = web.Lists[specificList];
var contentType = list.ContentTypes[0]; // Select first contenttype. Change this if you need a different contentType
foreach (SPField field in contentType.Fields)
{
if (!field.Hidden
&& (field.ShowInEditForm == null
|| !field.ShowInEditForm.Value)) // Replace ShowInEditForm with the form you need
{
var title = field.Title;
var description = field.Description;
var parentList = field.ParentList;
var references = field.FieldReferences; // contains names of fields referenced in computed fields
if (references != null)
{
foreach (string reference in references)
{
var test = parentList.Fields.GetField(reference);
}
}
}
}
I think the best way to go is to get the fields from the content type and not the list itself. That way you'll get only the fields visible in the form.
var list = web.Lists[specificList];
var contentType = list.ContentTypes["Document"];
foreach (SPField field in contentType.Fields)
{
if(!field.Reorderable || contentType.FieldLinks[field.Id].Hidden)
{
continue;
}
//Process fields
}
You may ask "Why Reordable=false?". Well, generally custom fields do not set this property so it is a nice way to filter them.
Also I didn't invent this code. This code is taken from code behind class of SharePoint standard content type fields reorder page (using reflection).

Categories