I have versioning and checkin/checkout enabled in a SharePoint 2010 list, and for business-related reasons, would like to update information in a field: overwriting the field data for all versions in a similar manner and in place so that the version numbers do not change.
If I call SPListItemVersion.ListItem.UpdateOverwriteVersion(), it fails stating that I need to check out the item before making changes to it. Makes sense. So I precede the update statement with SPListItemVersion.ListItem.CheckOut() statement, attempt the update, and receive an error that I cannot overwrite a published version. I've also attempted to precede the check out with SPSite.AllowUnsafeUpdates = true, setting it back to false after the update call, but the latter error still occurs. Any ideas?
Stripped code below:
foreach (SPListItemVersion itemVersion in item.Versions){
itemVersion.ListItem.File.CheckOut(SPFile.SPCheckOutType.Online, itemVersion.ListItem.File.TimeLastModified.ToString());
site.AllowUnsafeUpdates = true;
itemVersion.ListItem["FieldName"] = "changed value here";
itemVersion.ListItem.UpdateOverwriteVersion();
site.AllowUnsafeUpdates = false;
itemVersion.ListItem.File.CheckIn("Updated list item version", SPCheckinType.OverwriteCheckIn);
}
To anyone that may find themselves facing this issue, you do not need to toggle the AllowUnsafeUpdates field. What worked for me is replacing the itemVersion.ListItem.UpdateOverwriteVersion() statement with itemVersion.ListItem.SystemUpdate(false). The parameter passed in tells SharePoint to not create a new version when updating.
Edit: This answer only updates the current item again. SPListItemVersion field references are available via a get only; it appears this is not possible in the object model.
Related
I have an XPage that is doing an #DbLookup with a user's input and trying to find that value in a view in a different database yet on the same server.
I have already verified that the view is in fact sorted by the first column and therefore #DbLookup friendly. The following code below appears in the server-side Javascript OnClick event handler for a button on my XPage.
My problem is that the an error occurs when trying to assign the value of lRep to the 'firstNameLabel'. lRep is returning a null value from the dbLookup even though the a record under the 'FirstName' field exists with the key 'P301993'. This dbLookup should be finding a returning a single 'FirstName' result. However, it is not.
var resultLabel = getComponent("firstNameLabel");
var dbName = new Array(#DbName()[0],"UKCSandbox.nsf");
var lRep = #DbLookup(dbName,"customerLookup","P301993","FirstName");
resultLabel.setValue(lRep.toString());
Unless your formatting was lost in copy and paste, your code has flaws. This is not Java, this is JavaScript. Line endings matter and functions don't act on the object, but return a value. Also #DbLookup returns a string when you have exactly one match, so checking for string doesn't help you.
Your code should look like that:
var ukcNumber = Registration.getItemValueString('UKCNumber').toUpperCase();
var resultLabel = getComponent("ukcNumberLabel");
var dbName = #DbName();
dbName[1] = "UKC\\UKCSandbox.nsf";
var lRep = #DbLookup(dbName,"customerLookup",ukcNumber,1);
resultLabel.setValue((lRep) ? "Success" : "Failed");
Does that work for you?
Update: 2 things to check:
does the lookup work in the same database using #DbName?
XPages have the same security constraints as Java agents. Do you have enough rights in the server document to do a 'get value from other database'? Default is No!
Have you tried making the dblookup work outside of xpages, i.e. with ScanEZ or in the Notes client?
Check your ukcNumber variable so it contains a value.
Edit
Check so the user has rights to do the lookup in the other database.
Also try a similar code on an old Notes Form and see if you get the same result.
Why can't you use keyword '[FAILSILENT]' in your #DBLookup call. It'll return "", if no entry matches with your key.
If you still have issues, use SSJS/java code to see where it's breaking up.
In CRM 2011, under Account, there is the ability to add Connection. After clicking add Connection, you can browse/search for Name which defaults to "Contact". Is there a way to switch "Contact" to "Account" by default without having to switch the select box?
Apparently is just doing this:
document.getElementById("record2id").setAttribute("defaulttype", "1");
But i do a little search and this not work for the dialog of connections, check this alternative.
This doesn't work with connections.
With connections the object type code for the lookup is set in the Mscrm.Connection.preSelectObjectType function in Microsoft Dynamics CRM\CRMWeb_static\entities\connection.js.
There is a line like
$v_2.set_defaultType($v_3);
where the object type is set. $v_3 is set depending on the chosen role.
So you need to change it to
$v_2.set_defaultType(Mscrm.EntityTypeCode.Account.toString());
But you will lose the role based lookup configuration, so you might want to modify that. Plus it is unsupported and you will need to take into account the updating behavior when installing new rollups that change the connection.js (i.e. copy newer connection.js files by hand from an updated system, and customize them again).
Here are two approaches. Both works, but the first adds the type record Icon to the loockup field even if it empy. The second doesn't do that but a little bit more risky as it depends on the internal method names.
1st method:
if (IsNull(Xrm.Page.getAttribute('record2id').getValue())) {$("#record2id")[0].DataValue = [{ "type": scrm.EntityTypeCode.SystemUser.toString() }];}
2nd Method
document.original_preSelectObjectType = Mscrm.Connection.preSelectObjectType;
Mscrm.Connection.preSelectObjectType = function (roleLookup, peerRoleLookup) {
if (IsNull(roleLookup.DataValue) && IsNull(peerRoleLookup.DataValue) && !window.event.srcElement.DataValue) {
var $v_0 = window.event.srcElement;
$v_0.defaulttype = Mscrm.EntityTypeCode.SystemUser.toString();
$v_0.DefaultViewId = "";
$v_0.Lookup(true, false, null, false);
}
else {
document.original_preSelectObjectType(roleLookup, peerRoleLookup); }}
I am using the following code to update an entity.
Service.Update(_policy);
where policy is a class generated using CrmSvcUtil.exe
public partial class new_policy : Microsoft.Xrm.Sdk.Entity, System.ComponentModel.INotifyPropertyChanging, System.ComponentModel.INotifyPropertyChanged
I retrieve the policies using LINQ, then update one attribute (an EntityReference) and then attempt the update
When this code runs I get the following error message:
EntityState must be set to null, Created (for Create message) or
Changed (for Update message)
There are other entities generated in the same way that I can update.
I tried
_policy.EntityState = EntityState.Changed
but then I get a message saying
The entity is read-only and the 'EntityState' property cannot be
modified. Use the context to update the entity instead.
Does anyone know what is causing this?
You have to tell your crmContext (use appropriate name) what to do with the changes.
You should add crmContext.UpdateObject(contact); before crmContext.SaveChanges();
See also How to update a CRM 2011 Entity using LINQ in a Plugin?
To avoid the problem you can simply use update-helper-objects instead of using the retrieved record:
var policyUpdater = new Policy { Id = _policy.Id, FieldToUpdate = "newValue" };
service.Update(policyUpdater);
Note: Properties of the update-helper-object that aren't set are simply ignored. The update won't set the corresponding record fields to null
I had the same problem. I switched from using
context.Update(object)
to
context.UpdateObject(object)
and it worked.
This worked for me:
recordToUpdate.EntityState = EntityState.Changed;
(recordToUpdate is an Entity to be updated)
Turns out it was an issue with my linq query that was retrieving the entity in the first place. When I replaced this with a query expression it worked okay.
Time to brush up on my linq!
I have the following helper method that returns the value from a field.
public static string GetValueFrom(SPListItem item, string fieldName)
{
string value = string.Empty;
if (item.Fields.ContainsField(fieldName))
{
SPField field = item.Fields.GetField(fieldName);
if (item[field.InternalName] != null)
{
value = item[field.InternalName].ToString();
}
}
return value;
}
However for one Field (normal Choice Field) I am getting a ArgumentExecption on this line
if (item[field.InternalName] != null)
I am using
SPListItem item = list.GetItemById(itemId);
To get the item.
I cant find why I am getting the exception when I am checking to see if the field exists?
Any ideas as to why I am getting this Exception for only one field.
Update.
When debugging
The call to GetField() returns the correct field object.
Field.InternalName contains the correct Internal name of the field
If I try and access the value using item["internal name of the field"] it still throws and exception for only this one field.
Sometimes strange things happens and we do not have logical answer to those questions. Try by deleting the list and then creating the list again from scratch. DO NOT try to save it as template and DO NOT try to create the list from that template.
One possible reason of such type of ugly messages is that the security/permissions are not allowing to manipulate that field/column.
Another possible reason of such type of unwanted/unexpected messages is that when the field was created for the first time, its data type was different and later on it was changed to choice. Technically there should be no problem in doing so but sometimes we face odd behavior.
Have you tried debugging? Questions you should answer (because we can't):
Is field a valid value, or null, after the call to GetField()?
If field is not null, what does field.InternalName actually return?
If field.InternalName returns a valid value, can you access it by hard-coding that value in the indexer? i.e. item["fieldInternalName"]
Finding that information may help you solve the problem yourself, but if it doesn't add it to your post so the community has a better chance of helping you.
I do experienced this many a times. The reason for this is if you are logged-in as a non Admin Account(System Account) the default List View Lookup Threshold for the User is 8 for the lookup columns. i.e for the default view the user can access upto the 8 lookup fields only. If you change the List Throttling to >8 it will be resolved. But increasing this will degrade the performance.
Go to Central Admin >> Manage Web Applications >> Select the Web Application >> General Settings Dropdown >> Resource Throttling >> Change the "List View Lookup Threshold" to more than 8
Thanks,
-Codename "Santosh"
I'm having trouble figuring out how to add a custom column type to a list with the object model.
SPFieldCollection.Add() has a parameter SPFieldType, but that must be one of the enumerated values in the Microsoft.SharePoint.SPFieldType enumeration, thus it cannot be used to create columns of a custom type.
I next attempted using SPFieldCollection.CreateNewField() but when I call SPField.Update() on the returned value I get an exception: "ArgumentException was unhandled. Value does not fall within the expected range.".
I see a reference to SPFieldCollection.AddFieldAsXml() here: How do I add custom column to existing WSS list template but there's hardly any info and I'm not sure that's the right track to take.
UPDATE: I found a post on AddFieldAsXml: http://weblogs.asp.net/bsimser/archive/2005/07/21/420147.aspx and it turns out it's very easy and worked well for me. Posting anyway in hopes it will help someone else.
SPFieldCollection.AddFieldAsXml() is the way to go as far as I can tell. See here for an example: http://weblogs.asp.net/bsimser/archive/2005/07/21/420147.aspx
Try with:
SPField newField = null;
newField= web.Fields.CreateNewField("MyFieldTypeName", fieldName);
web.Fields.Add(newField);
newField = web.Fields[fieldName];
// set some properties
newField.ShowInDisplayForm = false;
newField.ShowInViewForms = true;
newField.Update();