The file has been modifed by error in sharepoint - sharepoint

I am getting the following error when i try to update the item's name in the sharepoint
document library. The item is of type document set and its default values is loaded using javascript. In the Item added event we are updating with the new changed item's name value. But in the item.update() code statement i am getting following error.
The File CZY14389 has been modified by domain\username on current date.
Please provide your commens on resolving this.

You cannot change the name of a sharepoint document like that. You need to "move it".
Item.Update();
Item.File.MoveTo(Item.ParentList.RootFolder.Url + "/" + newFileName, false);
Item.File.Item["FileRef"] = newFileName;
Item.File.Update();

before you update item name and call item.update(), can you try to refresh your item like this:
item = item.ParentList.GetItemById(item.ID);
item.name = "xyz";
item.update();

this can sometimes happen in event handler. the problem is the updation process in the event handler is not as the same of the workflow. In event handler for updating you have to use the followitn steps. Dont use Item.Update() as in workflow.
Follow the steps:
• call and disable event firing before your code with : base.EventFiringEnabled = false;
•update your item by calling item.systemUpdate(false);
•enable event firing with : base.EventFiringEnabled = true;

Disable event firing and call your update code, dont forget to enable event firing.
HandleEventFiring handleEventFiring = new HandleEventFiring();
handleEventFiring.DisableHandleEventFiring();
try
{
item.Update();
//if item.Update doesnt work then use(For me item.update worked only on my local not on prod then i used the below)
//item.SystemUpdate(false)
}
finally
{
handleEventFiring.EnableHandleEventFiring();
}
public class HandleEventFiring : SPItemEventReceiver
{
public void DisableHandleEventFiring()
{
//obsolete
//this.DisableEventFiring();
this.EventFiringEnabled = false;
}
public void EnableHandleEventFiring()
{
//obsotete
//this.EnableEventFiring();
this.EventFiringEnabled = true;
}
}

Related

How do I attach data to custom fields on INTranCost during release of POReceiptEntry?

I need to attach custom data into new fields added to INTranCost when the PO Receipt occurs.
Following the breadcrumbs, it seems that POReceiptEntry -> Release Action eventually calls INDocumentRelease.ReleaseDoc that eventually creates INTranCost. I tried extending both POReceiptEntry and INDocumentRelease to add an event for INTranCost_RowInserted to publish a PXTrace message, but the trace doesn't appear, telling me that I'm not hitting the event that I expected. (Which explains why the real business logic I need included didn't fire.)
protected virtual void _(Events.RowInserted<INTranCost> e)
{
PXTrace.WriteInformation("This is it!");
}
Of course, I want to put real code in this spot, but I am just trying to make sure I'm hitting the event properly. This works on pretty much everything else I've done, including attaching similar data to INTranExt fields. I cannot get it to work for INTranCost so that I can add to INTranCostExt. At this point, I can't determine if it is location (which graph extension) or a special methodology required for this special case.
I also tried overriding events and putting a breakpoint on the code, but it's like I'm not even on the same process. (Yes, I checked that I am connected to the right Acumatica instance and that I have no errors.)
What event in which graph is required to capture the creation in INTranCost for a PO Receipt to update custom fields in INTranCostExt?
Using Request Profiler, I was able to determine that I was close but not deep enough. While the INTranCost object to insert was built in INDocumentRelease FILE, the actual insert was processed in INReleaseProcess graph in that same file.
I only need to execute this "push" from the data captured on the POLine when the INTranCost record is created, and LineNbr is a key field and therefore never updated after it is set. I need to be sure that I have enough data to make the connection back, and the primary key links me back to the INTran easily. That subsequently gets back to the POReceiptLine to the POLine where the data is maintained that needs the "current value" to be captured when the transaction is posted. Since I need to update the DAC Extension, I need to use an event that will allow an existing DAC.Update to apply my values. Therefore, I added an event handler on INTranCost_LineNbr_FieldUpdated since that value should not be "updated" after it is set initially.
Code that accomplished the task:
public class INReleaseProcess_Extension : PXGraphExtension<INReleaseProcess>
{
public override void Initialize()
{
base.Initialize();
}
protected virtual void _(Events.FieldUpdated<INTranCost.lineNbr> e)
{
INTranCost row = (INTranCost) e.Row;
INTran tran = PXSelect<INTran,
Where<INTran.docType, Equal<Required<INTran.docType>>,
And<INTran.refNbr, Equal<Required<INTran.refNbr>>,
And<INTran.lineNbr, Equal<Required<INTran.lineNbr>>
>>>>
.SelectSingleBound(Base, null, row.DocType, row.RefNbr, (int?) e.NewValue);
if (tran?.POReceiptType != null && tran?.POReceiptNbr != null)
{
PXResultset<POReceiptLine> Results = PXSelectJoin<POReceiptLine,
InnerJoin<POLine, On<POLine.orderType, Equal<POReceiptLine.pOType>,
And<POLine.orderNbr, Equal<POReceiptLine.pONbr>,
And<POLine.lineNbr, Equal<POReceiptLine.pOLineNbr>>>>,
InnerJoin<POOrder, On<POOrder.orderType, Equal<POLine.orderType>,
And<POOrder.orderNbr, Equal<POLine.orderNbr>>>>>,
Where<POReceiptLine.receiptType, Equal<Required<POReceiptLine.receiptType>>,
And<POReceiptLine.receiptNbr, Equal<Required<POReceiptLine.receiptNbr>>,
And<POReceiptLine.lineNbr, Equal<Required<POReceiptLine.lineNbr>>>>>>.
SelectSingleBound(Base, null, tran.POReceiptType, tran.POReceiptNbr, tran.POReceiptLineNbr);
if (Results != null)
{
foreach (PXResult<POReceiptLine, POLine, POOrder> result in Results)
{
POReceiptLine receipt = result;
POLine line = result;
POOrder order = result;
POLineExt pOLineExt = PXCache<POLine>.GetExtension<POLineExt>(line);
INTranCostExt iNTranCostExt = PXCache<INTranCost>.GetExtension<INTranCostExt>(row);
if (pOLineExt != null && iNTranCostExt != null)
{
Base.Caches[typeof(INTranCost)].SetValueExt<INTranCostExt.usrField>(row, pOLineExt.UsrField);
}
}
}
}
}
}

How to prevent global event handlers from firing caused by an API call

I have a custom module that uses Kentico API (DocumentHelper) to update certain fields of my document and then publish but I do not want it to trigger the event handlers that are linked to my document page type. I tried adding comments to .Publish("admin_edit") hoping that I can catch it from the WorkflowEventargs parameter but the VersionComment property always return null. Is there a way to accomplish this in Kentico?
update field:
var document = DocumentHelper.GetDocument(documentID, tree);
var workflowManager = WorkflowManager.GetInstance(tree);
var workflow = workflowManager.GetNodeWorkflow(document);
if (workflow != null)
{
document.CheckOut();
document.SetValue("SomeFIeld", "some value");
document.Update(true);
document.CheckIn();
document.Publish("admin_edit");
}
event handler:
public override void Init()
{
WorkflowEvents.Publish.After += Publish_After;
}
private void Publish_After(object sender, WorkflowEventArgs e)
{
if (!string.IsNullOrEmpty(e.VersionComment) &&
e.VersionComment.Contains("admin_edit"))
return;
}
You always get null for Version information, because that is related to the 'Page versioning' events, specially for 'SaveVersion'. You can find more about that on this link. If you expand 'Properties' you will see which properties are populated for the specific event. In your case, you can try something like this, to add your message for last version and then check for that comment on 'Publish_After' event, see code bellow:
var document = DocumentHelper.GetDocument(documentID, tree);
var workflowManager = WorkflowManager.GetInstance(tree);
var workflow = workflowManager.GetNodeWorkflow(document);
if (workflow != null)
{
document.CheckOut();
document.SetValue("SomeFIeld", "some value");
document.Update(true);
document.CheckIn(versionComment: "admin_edit");
document.Publish();
}
and then, in event handler, take last version and check for comment like this:
if (e.PublishedDocument?.VersionHistory?.Count > 0)
{
var lastVersion = e.PublishedDocument.VersionHistory[0] as VersionHistoryInfo;
if (lastVersion.VersionComment.Equals("admin_edit"))
{
return;
}
}
NOTE: In case that you have a lot of concurrent content editors, there is a chance that your last version is not version from API (someone changed content and saved it right after your API call made change). There is a low chance for that, but still is possible. If this is something that you will use often, you must take it in consideration. This code is tested for Kentico 11.

SharePoint workflow task with custom content type after properties issue

I made a workflow for "Corrective Action". Here the issuer will issue the CA to a user. If he replies to that then the approver should review it. Here for approver i created a content type named "CA Review" for the Task where I added a field "Outcome" which is a drop down.
In the workflow, for the review task, in the method invoking i am attaching the content type to the task. This is working fine and i am able to see the "outcome" in the task edit form.
In the event of task changed, i need the value of "outcome" to set the other filed. Here i am using after properties of the task changed event. But this returns "null". Here is my code for getting the outcome value.
private void checkTheRespondeApproval(object sender, ConditionalEventArgs e)
{
var props = this.onReviewTaskChanged_AfterProperties1.ExtendedProperties[GetWorkflowFieldId("Outcome")];
e.Result = (props.ToString() == "Approved");
}
Here "props" is getting "Null". Please help me to get the outcome value. The code for "GetWorkflowFieldID" is as follows;
private Guid GetWorkflowFieldId(string pFieldName)
{
foreach (SPField item in workflowProperties.Item.Fields)
{
if (item.Title == pFieldName)
return item.Id;
}
return Guid.Empty;
}
Ok Guys,
I found the answer. The problem is for the field ID I am looking into wrong collection. I should get the field id of the content type. The following is the function I wrote to get the ID. It is working now.
private Guid GetContentTypeFileID(string pFieldName)
{
foreach (SPField item in workflowProperties.Web.ContentTypes["CAReview"].Fields)
{
if (item.Title == pFieldName)
return item.Id;
}
return Guid.Empty;
}
I hope this will help you too.

CRM 2011 KeyNotFoundException exception

I am new to CRM development.
I have a Custom Entity "customer". This Entity has a Field called "defaultcustomer", which can be TRUE or FALSE. I am working on a Plug-In where i need to set the "defaultcustomer" to FALSE for all the "Customers". I am doing it as below:
FACTS:
I have registered the plugin for the entity "customer" itself. So when the Entity "customer" is updated, the plugin fires.
private void MakeAllNonDefault()
{
try
{
QueryExpression query = new QueryExpression("customer");
query.ColumnSet = new ColumnSet("defaultcustomer");
EntityCollection retrieved = service.RetrieveMultiple(query);
foreach (Entity myCustomer in retrieved.Entities)
{
myCustomer["defaultcustomer"] = false;
service.Update(myCustomer);
}
}
catch (Exception ex)
{
throw new InvalidPluginExecutionException("An error occurred in MakeAllNonDefault(): " + ex.ToString());
}
}
ERROR:
It throws error on this line:
myCustomer["defaultcustomer"] = false;
System.Collections.Generic.KeyNotFoundException:
The given key was not present in the dictionary.
The error means that particular field is not present in the collection of properties. In CRM, only properties that have been set or updated are included.
Try something like:
foreach (Entity myCustomer in retrieved.Entities)
{
if (myCustomer.Attributes.ContainsKey("defaultcustomer"))
{
myCustomer["defaultcustomer"] = false;
}
else
{
myCustomer.Attributes.Add("defaultcustomer", false);
}
service.Update(myCustomer);
}
Have you double checked that the field really is called defaultcustomer?
If it's a custom entity then it's likely the field begins with a prefix, for instance new_defaultcustomer. Make sure you are using the name of the field, not the display name.
The solution posted by #glosrob seems fine. Are you still getting "The given key was not present in the dictionary"?
Try to use ITracingService to get more information about the plugin execution flow.
While Update all Crm fields are False accept that what you Update the field. For that you can use Pre/Post Images in Plugin. you will found that crm field key and update what you need.

why my sharepoint workflow always stop when i use this code?

I need to find an user in a list to set the assignedto task property, these informations are in a list. So i use this method :
public static SPUser GetSPUser(SPListItem item, string key){
SPFieldUser field = item.Fields[key] as SPFieldUser;
if (field != null)
{
SPFieldUserValue fieldValue = field.GetFieldValue(item[key].ToString()) as SPFieldUserValue;
if (fieldValue != null)
{
return fieldValue.User;
}
}
return null;
}
The problem is that when i use this method or this part of code, my workflow stop without saying anything. Here an exemple of code when i use it :
using (SPSite site = new SPSite(adress_of_my_site))
{
using (SPWeb web = site.OpenWeb())
{
SPList list = web.Lists["Acteurs du projet"];
SPView view = cobj_ListeDesActeursDuProjet.DefaultView;
SPListItemCollection itemcollection = list.GetItems(view);
foreach (SPListItem item in itemcollection)
{
SPUser lobj_acteur = Utilities.GetSPUser(item,"acteur");
// Dictionary<string,class>
ActeursDuProjet[item["Rôle"].ToString()] =
new ActeursDuProjet()
{
Login = lobj_acteur.LoginName,
Email = lobj_acteur.Email
};
}
}
}
If i comment the content of my foreach my workflow continue as well...
If anybody have an idea it will be cool.
Regards,
Loïc
edit: problem in the code
Here are some debugging tips that might help:
ULS logs
Any exceptions should be reported here in some detail.
Enable debugging for all .NET code
This will cause the debugger to break whenever an exception occurs in SharePoint as well as your code. The downside is that the debugger will break on 'normal' exceptions that cause no side effects. So don't be misled!
To enable: Go to Debug, Exceptions and tick Common Language Runtime Exceptions. Also go to Tools, Options, Debugging and untick Enable Just My Code. Then attach to w3wp.exe.
Commenting code
You could also comment out all of your code. If the workflow step fails, you know there is a problem elsewhere. If the workflow step passes, then start uncommenting code until it fails - then you know where to look.
I tried commenting this above but it didn't format nicely so here it is.
It probably is fine, but this looks fishy to me:
// Dictionary<string,class>
ActeursDuProjet[item["Rôle"].ToString()] =
new ActeursDuProjet()
{
Login = lobj_acteur.LoginName,
Email = lobj_acteur.Email
};
I would think it would be something like:
// dictionary declared somewhere earlier
Dictionary<string,ActeursDuProjet> roles = new Dictionary<string,ActeursDuProjet>();
// inside the foreach
string role = item["Rôle"].ToString();
if (!roles.ContainsKey(role))
{
ActeursDuProjet foo = new ActeursDuProjet();
foo.Login = lobj_acteur.LoginName;
foo.Email = lobj_acteur.Email;
roles.Add(role, foo);
}

Resources