When I try to create a new list item with the basic calendar/list fields everything works perfectly. However, when I try to do so with a "non-standard" field i.e. a field I added, I am getting a "field not recognized" error.
The field is clearly there! Is there some special way I need to populate these custom fields?
// get a specific list
ISiteListsCollectionPage list = await graphClient.Sites["root"].Lists.Request()
.Filter($"DisplayName eq 'Outlook Integration'").GetAsync();
// create a dictionary of [calendar] list properties
Dictionary<string, object> props = new Dictionary<string, object>();
// populate properties, all of these work just fine
props.Add("Title", evt.Subject);
props.Add("Location", evt.Location?.DisplayName);
props.Add("EventDate", utcStart.ToString("yyyy-MM-ddTHH:mm:ssK"));
props.Add("EndDate", utcEnd.ToString("yyyy-MM-ddTHH:mm:ssK"));
props.Add("Description", Regex.Replace(evt.Body.Content, "<.*?>", String.Empty)); // remove HTML content
// populate custom properties
props.Add("ResourceID", evt.Id); // throws error: Field 'ResourceID' is not recognized
// create list item with our properties dictionary
var newItem = new ListItem
{
Name = "My New Event",
Fields = new FieldValueSet()
{
AdditionalData = props
}
};
// call the service and get the result
var newListItem = await graphClient.Sites["root"].Lists[list[0].Id].Items.Request().AddAsync(newItem);
This is the complete list of fields on my list:
Here you can see the display name is "ResourceID" whereas the API name is "O365EventId." However, both result in the same error, "Field not recognized."
Note: ResourceID is one of the fields that I added. How can I set the value of this field via the Graph API?
Marc is right by saying in comment regarding column name, the provided screenshot displays Column.displayName which is
The user-facing name of the column.
but what actually FieldValueSet.AdditionalData expects as a key is Column.name which is:
The API-facing name of the column as it appears in the fields on a
listItem. For the user-facing name, see displayName.
In your case most likely displayName and name properties are different, you could verify it via following endpoint:
https://graph.microsoft.com/v1.0/sites/root/lists/Outlook Integration/columns
and that's the reason why this error occurs.
Via the Graph API client (C#), you can see a list of all columns for any given list like so:
// get specific list by name
ISiteListsCollectionPage list = await graphClient.Sites["root"].Lists.Request()
.Filter($"DisplayName eq 'YOUR_LIST_NAME_HERE'").GetAsync();
// get columns and output them to the log as a serialized object
var listColumns = await graphClient.Sites["root"].Lists[list[0].Id].Columns.Request().GetAsync();
logger.LogInformation($"List Columns Object: {JsonConvert.SerializeObject(listColumns).ToString()}");
Related
I would like to get a list of Fields of a content type. I am hoping to get a list of just the fields that show up on the Edit Form or Edit Properties of an uploaded document.
Below code will get me the fields list, but I cannot distinguish what fields are just shown on the Edit Form / Display Form.
I think I need to look at FieldLink Collection as that should have a ShowInForm property. But that "ShowInForm" was not a valid property in that collection.
I also did some googling but I can see how to setShowInForm, but not how to get that value for the field.
If you have any suggestions, please let me know.
ClientContext clientContext = new ClientContext(site);
//// Get the content type using ID: 0x01003D7B5A54BF843D4381F54AB9D229F98A - is the ID of the "Custom" content Type
string contentTypeID = GetContentTypeGUID(contentType, site);
ContentType ct = clientContext.Web.ContentTypes.GetById(contentTypeID);
//// Gets a value that specifies the collection of fields for the content type
FieldCollection fieldColl = ct.Fields;
clientContext.Load(fieldColl);
clientContext.ExecuteQuery();
//// Display the field name
foreach (Field oField in fieldColl)
{
// Code for each Field
}
Per mt test, the value of ShowInForm is in the field.SchemaXml property.
I'm trying to retrieve only the attributes for a certain entity, that have changed metadata since the last metadataquery - for example: if a user changes the requirement on a certain field of a certain entity, and saves and publishes this change, I want a plugin that fires on message Publish & PublishAll to let me know what attribute and which metadata of that attribute has changed.
This is the code I have so far, based on this example on MSDN: https://msdn.microsoft.com/en-us/library/jj863605.aspx?f=255&MSPPError=-2147217396
I get the attributes for the three entities that are listed in includedEntities, so no problem there.
I get values for RequiredLevel and IsValidForAdvancedSearch, the two attribute properties listed in attributeProperties and the ones I want to watch while the rest returns null, so again, no problem here.
The attributeFilter also does what it's supposed to do: I only get datafields (attributes that do not describe another attribute), so once again: no problem.
The clientversionstamp I pass on is retrieved from a configurationparameter I created, which I update after every query. By watching it during debug, I know that it's the correct value - so I'm quite sure that's not the problem either.
So what is the problem? For each entity, I still have some (about half) of the attributes that are added to the collection of changed attributes in the response, although I didn't change anything.
If I do change something in metadata, that attribute does get added to the response collection as well, so my code does pick up the change. However, I still get a lot more data than I want - the goal is to only get that one attribute that has changed. What am I missing?
MetadataFilterExpression EntityFilter = new MetadataFilterExpression(LogicalOperator.And);
EntityFilter.Conditions.Add(new MetadataConditionExpression("LogicalName", MetadataConditionOperator.In, includedEntities));
MetadataPropertiesExpression EntityProperties = new MetadataPropertiesExpression()
{
AllProperties = false
};
EntityProperties.PropertyNames.AddRange(new string[] { "Attributes" });
MetadataConditionExpression optionsetAttributeName = new MetadataConditionExpression("AttributeOf", MetadataConditionOperator.Equals, null);
MetadataFilterExpression AttributeFilter = new MetadataFilterExpression(LogicalOperator.And);
AttributeFilter.Conditions.Add(optionsetAttributeName);
MetadataPropertiesExpression AttributeProperties = new MetadataPropertiesExpression() { AllProperties = false };
foreach (string attrProperty in attributeProperties)
{
AttributeProperties.PropertyNames.Add(attrProperty);
}
EntityQueryExpression entityQueryExpression = new EntityQueryExpression()
{
Criteria = EntityFilter,
Properties = EntityProperties,
AttributeQuery = new AttributeQueryExpression()
{
Properties = AttributeProperties,
Criteria = AttributeFilter
}
};
RetrieveMetadataChangesRequest req = new RetrieveMetadataChangesRequest()
{
Query = entityQueryExpression,
ClientVersionStamp = clientVersionStamp
};
return (RetrieveMetadataChangesResponse)service.Execute(req);
How do you save "Value" and "DataServiceCollection" objects that are part of another SharePoint list item? These are the only properties in my model that are not getting saved.
The generated Food SharePoint model has these sort of properties:
public class Food
{
DataServiceCollection<FoodIngredientValue> Ingredient;
FoodStateValue State;
string _StateValue
}
First, I don't know why there are two ways to add a state value in the model generated by SharePoint. I try populating either one and the state value doesn't populate in SharePoint.
Secondly, I tried populating the Ingredient collection through hard coding FoodIngredientValue objects to the food model before saving and also by querying SharePoint and assigning them to the Ingredient property but it doesn't get saved in SharePoint.
I add a new food item to the SharePoint list using the code below and I verified all three properties are populated in my model but none of them get saved.
public bool Insert(Food food)
{
var dataContext = new FoodDataContext(new Uri(EndpointUrl)) { Credentials = CredentialCache.DefaultNetworkCredentials };
dataContext.AddToFoods(food);
var response = dataContext.SaveChanges().FirstOrDefault();
return response.StatusCode == 201;
}
This was a great blog post explaining how to link complex list items (DataServiceCollecton and Value objects) in the SharePoint oData API:
http://blog.heeresonline.com/2014/07/sharepoint-wcf-dataservices-choice-lookup-column-editing/
The important thing to remember is to add the new item to the data context before you begin populating complex fields of type DataServiceCollection or Value objects. In the case of properties of type DataServiceCollection, there is a little more work that needs to be done to link them properly so they are saved in the data context as shown below for Ingredient. Here is an example of the code that finally worked:
var foodItem = new FoodItem();
dataContext.AddToFoods(foodItem); // Add to context before populating fields so the values are tracked.
foodItem = Mapper.Map(newFood, foodItem);
// DataValue Properties like StateValue objects can now be added since it is tracked by the context.
var state = StateValue.CreateStateValue("Montana");
foodItem.StateValue = state;
// Need to link special DataServiceCollection lists like Ingredient using a reference.
if (newFood.Ingredient != null)
{
newFood.Ingredient.ForEach(c =>
{
var ingredient = FoodIngredient.CreateFoodIngredientValue(c);
dataContext.AttachTo("FoodIngredientValue", ingredient);
foodItem.FoodIngredient.Add(ingredient);
dataContext.AddLink(foodItem, "FoodIngredient", ingredient);
});
}
I have been able to programmatically add external (i.e. BDC) lookup fields to a list and I have also been able to add dependent external lookup fields to the same list. What I have not been able to figure out is how to programmatically add the dependent external lookup fields to the list's default view.
This article on MSDN gives an example of how to add a regular dependent lookup field to an SPView -but I have yet to find an example that shows how to programmatically add a dependent external lookup field to an SPView.
Below is the code in the FeatureActivated method of my EventReceiver that I am using to add the dependent external lookup fields to my SharePoint list and my attempt at adding the field to the list's default view.
var web = ((SPSite)properties.Feature.Parent).RootWeb;
var list = web.Lists.TryGetList("MyList");
var fldName = "EmployeeID";
var fld = list.Fields.CreateNewField("BusinessData", fldName) as SPBusinessDataField;
fld.SystemInstanceName = lobSystemInstanceName;
fld.EntityNamespace = entityNamespace;
fld.EntityName = entityName;
fld.BdcFieldName = entityFieldName;
//The dictionary object defined below contains key/value pairs that represent the
//field name as a string along with a boolean flag that specifies whether or not
//the secondary field should be added to the default view.
var secondaryFieldNames = new Dictionary<string, bool>()
{
{"FirstName", true},
{"LastName", true},
{"Title", false}
}
fld.SetSecondaryFieldsNames(secondaryFieldNames.Select(e => e.Key).ToArray());
var view = list.Views.DefaultView;
foreach (var secFld in secondaryFieldNames)
{
var viewFieldName = String.Format("{0}: {1}", fldName, secFld.Key);
if (!view.ViewFields.Exists(viewFieldName) && secFld.Value)
{
view.ViewFields.Add(viewFieldName);
view.Update();
}
}
As mentioned previously, the primary lookup field and all secondary lookup fields are successfully added to the list. The primary lookup field is successfully added to the list's default view. The seconday fields are not.
Storing the viewfield collection in a variable did the trick for me (don't really know why).
foreach (var secFld in secondaryFieldNames)
{
var viewFieldName = String.Format("{0}: {1}", fldName, secFld.Key);
var viewFields = view.ViewFields;
if (!viewFields.Exists(viewFieldName) && secFld.Value)
{
viewFields.Add(viewFieldName);
view.Update();
}
}
Hi I have two Lists in sharepoint 2007.
I have a lookup column in on list which looks the other field.
I want to use the sharepoint object model to add an item to the second list.
How to i set the lookup field value. (The value is already in the other list).?
SPListItem Employee = web.Lists["Employee"].Items.Add();
Employee["Name"] = account.Name;
Employee["Department"] = <lookup value must come here>
Employee.Update();
Lookup fields will contain a combination of the row's id and the value of the column to display, separated by :#, in your case that could be 1:#HumanResources or 12:#Engineering.
So to reference a lookup simply setting the id won't be enough, instead the above mentioned string needs to be set. Luckily SharePoint provides the class SPFieldLookupValue that does exactly this:
var department = web.Lists["Department"].GetItemById(1);
var employee = web.Lists["Employee"].Items.Add();
employee["Name"] = account.Name;
employee["Department"] = new SPFieldLookupValue(department.ID, department.Title);
employee.Update();