In SharePoint Online, I'm having problems setting a site Managed Metadata column default value using CSOM (C#). For brevity, I've not included exception handling in my code. Here's what I have:
// Code snippet for what I'm trying to achieve
using (ClientContext ctx = NewCtx(SiteInfo.Url)) // NewCtx is just a static member I use to return a ClientContext object
{
Field taxColumn = (Field)ctx.Web.Fields.GetByTitle("myMMColumnName");
ctx.Load(taxColumn);
ctx.ExecuteQuery();
TaxonomyFieldValue termField = new TaxonomyFieldValue();
termField.Label = "My MM Term";
termField.TermGuid = "b269aef7-6f47-4b02-bf80-7edfb7166a30";
termField.WssId = -1;
taxColumn.DefaultValue = value;
// Place holder for added code (see below)
taxColumn.Update();
ctx.Load(taxColumn);
ctx.ExecuteQuery();
}
The value appears in the UI under Site Columns, but no associated item is created in the TaxonomyHiddenList, which makes sense because setting the lookup WssId to "-1" doesn't resolve and therefore, the default value doesn't have a lookup and appears empty in the list- and library-level column.
The closest resolution I found was an article (albeit not CSOM and linked below) suggested creating a "dummy" list item (against a list that was consuming the MM column). This would trigger the creation of the item in the TaxonomyHiddenList but the article suggests not committing the "dummy" item creation. I've tried this too, but seems to have no effect. This is the code I added to the place holder mentioned in the previous code block:
List myList = ctx.Web.Lists.GetByTitle("My List");
ctx.Load(myList);
ctx.ExecuteQuery();
TaxonomyField taxField = ctx.CastTo<TaxonomyField>(myList.Fields.GetByTitle("myMMColumnName"));
ListItemCreationInformation newItemInfo = new ListItemCreationInformation();
ListItem newItem = myList.AddItem(newItemInfo);
newItem["myMMColumnName"] = termField;
taxField.SetFieldValueByValue(newItem, termField);
The article uses the .SetFieldValue method, which isn't available in CSOM so I may well have assumed incorrectly that .SetFieldValueByValue is comparable.
Thanks for reading!
References:
Article - http://sharepointificate.blogspot.com/2014/04/setting-managed-metadata-column-default.html
SetFieldValue Method belongs to TaxonomyField class, it means the line:
Field taxColumn = (Field)ctx.Web.Fields.GetByTitle(taxFieldTitle);
needs to be replaced with:
var taxColumn = ctx.CastTo<TaxonomyField>(ctx.Web.Fields.GetByTitle(taxFieldTitle));
or
TaxonomyField taxColumn = ctx.CastTo<TaxonomyField>(ctx.Web.Fields.GetByTitle(taxFieldTitle));
Once TaxonomyField is initialized, the default value could be set as shown below:
//get taxonomy field
var taxColumn = ctx.CastTo<TaxonomyField>(ctx.Web.Fields.GetByTitle(taxFieldTitle));
ctx.Load(taxColumn);
ctx.ExecuteQuery();
//initialize taxonomy field value
var defaultValue = new TaxonomyFieldValue();
defaultValue.WssId = -1;
defaultValue.Label = termLabel;
defaultValue.TermGuid = termId.ToString();
//retrieve validated taxonomy field value
var validatedValue = taxColumn.GetValidatedString(defaultValue);
ctx.ExecuteQuery();
//set default value for a taxonomy field
taxColumn.DefaultValue = validatedValue.Value;
taxColumn.Update();
ctx.ExecuteQuery();
Note: TaxonomyField.GetValidatedString method is utilized for
validation of taxonomy field value which in turn includes the
resolving of WssId value
Update
Use Field.UpdateAndPushChanges method to propagate changesto all lists that use the field
So, replace:
taxColumn.Update();
ctx.ExecuteQuery();
with:
taxColumn.UpdateAndPushChanges(true);
ctx.ExecuteQuery();
Related
I need to create an item with Person/People field.
I am able to populate fields like Title, DateTime, TextField as seen below, but I am not able to populate Person field at all.
I have tried sending Display Name, User ID and UPN.
var fieldValueSet = new FieldValueSet();
fieldValueSet.AdditionalData = new Dictionary<string, object>();
fieldValueSet.AdditionalData.Add("Title#odata.type", "Edm.String");
fieldValueSet.AdditionalData.Add("Title", task.Title);
fieldValueSet.AdditionalData.Add("Plan#odata.type", "Edm.String");
fieldValueSet.AdditionalData.Add("Plan", plan.Title);
fieldValueSet.AdditionalData.Add("Assigned#odata.type", "Edm.String");
fieldValueSet.AdditionalData.Add("Assigned", assignee.UserPrincipalName);
fieldValueSet.AdditionalData.Add("DueDate#odata.type", "Edm.String");
fieldValueSet.AdditionalData.Add("DueDate", task.DueDateTime);
var listItem = new ListItem
{
Fields = fieldValueSet
};
await graphServiceClient.Sites["SPURL:/sites/ITOddeleni:"].Lists["ListName"].Items
.Request()
.AddAsync(listItem)
Does your user principal name look like an email? (e.g. some.person#yourtenant.onmicrosoft.com). If that is the case then you should probably try to convert it to a sharepoint-claim version: i:0#.f|membership|some.dude#yourtenant.onmicrosoft.com.
If you have an authenticated ClientContext in your app, then you could resolve the username by calling the SharePoint utility:
Utility.ResolvePrincipal(context, context.Web, userEmail, PrincipalType.User, PrincipalSource.All, null, true);
If you don't have a context then you can try and combine strings (not as robust, but should work as well).
This answer suggests that you should try and set the LookupId value for the field (sorta the same way you set user values using the SharePoint's REST api):
var assigneeLookupId = // Get the assignee's user id on the site (wssid)
fieldValueSet.AdditionalData.Add("AssignedLookupId#odata.type", "Edm.Int32");
fieldValueSet.AdditionalData.Add("AssignedLookupId", assigneeLookupId);
The following schema would allow you to insert multiple person values:
SOLUTION
After help from comments i got this answer which worked
{
"AssignedLookupId#odata.type" : "Collection(Edm.Int32)"
"AssignedLookupId": [1,2,3]
}
This approach is in line with the way MS Graph returns values for Lookup fields.
I am new to Sharepoint and currently I want to write a function where I can read and write data to Sharepoint pages. This is the structure of the URL I want to connect to read and write data: https://mycompany.sharepoint.com/sites/SubSite/SubSite1/SitePages/Home.aspx
Then, I open the connection to it by using:
ClientContext clientContext = new ClientContext("https://mycompany.sharepoint.com/sites/SubSite/SubSite1/");
clientContext.Credentials = new SharePointOnlineCredentials("user#mycompany.com", password);
I use SecureString for the password
Then, I load site pages in to a list and read each field to examine:
List colList = clientContext.Web.Lists.GetByTitle("Site Pages");
FieldCollection colfield = colList.Fields;
IEnumerable<Microsoft.SharePoint.Client.List> resultCollection = clientContext.LoadQuery(
clientContext.Web.Lists.Include(
list => list.Title,
list => list.Id));
clientContext.Load(colList);
clientContext.Load(colfield);
clientContext.ExecuteQuery();
Then I loop through every field to examine
for(int i = 1; i <= 4; i++){
ListItem lst = colList.GetItemById(i);
foreach (Field field in colfield){
clientContext.Load(field);
clientContext.ExecuteQuery();
var val = lst[field.Title];
}
}
I figured out that there are some fields in colList, such as: DataSource, etc. containing this exception:
The property or field has not been initialized. It has not been requested or the request has not been executed. It may need to be explicitly requested
My question is how can I properly connect to Sharepoint site pages to read and write data in them?
You are iterating through all the fields of colList but including only Id & Title fields in
clientContext.Web.Lists.Include(
list => list.Title,
list => list.Id));
That's why you are getting above exception.
You have to Include all the fields you want to retrieve OR just load the list clientContext.Load(colList); and don't Include anything if you want to retrieve all the fields.
I assigned Custom property to Taxonomy.I need to get the custom property value by passing Taxonomy Id by using programmaticaly with Ektron Framework Api.
I worked in Ektron 9.
Thanks in advance!
You can retrieve Taxonomy Custom properties by using the CustomPropertyObject class. I use a code similar to this one:
var customApi = new CustomPropertyObject();
var customPropertyId = 0; // Put here your custom property id
var taxonomyId = 0; // Put here your taxonomy Id
var customProperties = customApi.GetItem(taxonomyId, 2057 /* language code */,
EkEnumeration.CustomPropertyObjectType.TaxonomyNode, customPropertyId)
.Items.ToDictionary(i => i.PropertyId, i => i.PropertyValue.ToString());
You just need to put your own TaxonomyId, CustomPropertyID and language code.
Hope this helps,
Jonatan
I'm sure this is possible, I just haven't got the foggiest how or where to start.
So, I have an option set created in MS Dynamic CRM which gives me a list of countries, MyCountryOptionSet. Lovely.
However, I have a number of other .net, c# applications where users can enter free text. This is not so lovely.
As such, I would like to tie these down so only countries in present in MyCountryOptionSet can be used.
Therefore, I would like to bind the countries from MyCountryOptionSet to a drop down list in my .net applications.
How would I go about doing this?
Look into RetrieveAttributeRequest and IOrganizationService. This will allow you to get the countries defined in your option set. By casting the AttributeMetadata property on the response to PicklistAttributeMetadata.
The binding to controls will be UI technology specific so post more info.
use the crm apis to get option values as follows...
_serviceProxy = new OrganizationServiceProxy(serverConfig.OrganizationUri, serverConfig.HomeRealmUri,
serverConfig.Credentials, serverConfig.DeviceCredentials);
_serviceProxy.EnableProxyTypes();
_service = _serviceProxy;
RetrieveAttributeRequest retrieveAttributeRequest =
new RetrieveAttributeRequest
{
EntityLogicalName = EntityLogicalName,
LogicalName = optionSetLogicalName,
RetrieveAsIfPublished = true,
};
// Execute the request.
RetrieveAttributeResponse retrieveAttributeResponse =
(RetrieveAttributeResponse)_service.Execute(
retrieveAttributeRequest);
// Access the retrieved attribute.
PicklistAttributeMetadata retrievedPicklistAttributeMetadata =
(PicklistAttributeMetadata)
retrieveAttributeResponse.AttributeMetadata;
// Get the current options list for the retrieved attribute.
OptionMetadata[] optionList =
retrievedPicklistAttributeMetadata.OptionSet.Options.ToArray();
//Dictionary<int,string> LocalizedLabelDic = new Dictionary<int,string>();
List<ListItem> OptionSetItems = new List<ListItem>();
foreach (OptionMetadata o in optionList)
{
OptionSetItems.Add(new ListItem(o.Label.LocalizedLabels.FirstOrDefault(e => e.LanguageCode == 1033).Label.ToString(), o.Value.Value.ToString()));
}
then bind the listitem generic collectoin to ur asp.net drop down
You can query the CRM database directly for the values using a query like this:
select Value, AttributeName
from StringMap
where AttributeName = 'New_MySet' --schema name of the global option set
and ObjectTypeCode = 1 --changes based on entity type field is associated with
Once you have the results you can bind them to the list in your application.
I'm trying to add new values to a MS Dynamics CRM option set in C# with InsertOptionValueRequest, and when I do, some of the existing option set values get deleted.
The code I am using is as follows:
ovRequest = new InsertOptionValueRequest
{
AttributeLogicalName = strOptionsetName,
EntityLogicalName = strEntityName,
Label = new Label(strLabel, LanguageCode)
};
_service.Execute(ovRequest);
I then publish entity with:
pxReq1 = new PublishXmlRequest { ParameterXml = String.Format("<importexportxml><entities><entity>{0}</entity></entities></importexportxml>", strEntityName) };
ospService.Execute(pxReq1);
I am finding this is happening both with Local Option Sets and Global Option Sets and can't see any pattern in the value being deleted. Am I doing something wrong or is this a bug in the SDK?
PS, can someone add a insertoptionvaluerequest tag to this, because I think that tag would be most relevant to this post.
I have found an answer to my question. MS Dynamics is not deleting existing values, it is overwriting the label on existing option set values. This is definitely a bug as the command being run is InsertOptionValueRequest and there is a separate UpdateOptionValueReqequest for updating values.
To work around it, manually set the Value when inserting the record instead of relying on the system to generate one for you:
ovRequest = new InsertOptionValueRequest
{
AttributeLogicalName = strOptionsetName,
EntityLogicalName = strEntityName,
Label = new Label(strLabel, LanguageCode),
Value = MyNewValue
};
_service.Execute(ovRequest);