Guidance on creating non conflicting workflows - sharepoint

We have a SharePoint site that displays a calendar and manages appointments etc.
We are trying to automate several aspects of this system via workflows.
Indvidually each workflow works ok.
The problem is that we want them to run automatically when an item is modified. But sometimes a workflow itself modifies another item - which in turn triggers the workflows....
How do you avoid these race conditions?

Heads up: I haven't tested this with workflow specifically
For SP events you can do this programmatically through the list item event receiver.
When you attach the event receiver to the list you can explicitly disable event firing for a particular sequence. This stop the subsequent events from firing as a result of the initial event.
This behaviour should carry over to workflow, as long as you launch the workflow from the event receiver.
public class ListItemEventReceiver : SPItemEventReceiver
{
#region SPItemEventReceiver Interface
public override void ItemAdded(SPItemEventProperties properties)
{
this.DisableEventFiring();
// trigger your workflow here
this.EnableEventFiring();
}
}

Related

Use NewClassWizard in kentico admin

I want to create a custom page that allows me to track manually every data modification made by kentico in the database
I understood that I can implement it by code by using the NewClassWizard. But when done how I can use it in Kentico admin ?
I try to load it from Page Type module but can find a way to specify my custom class
Is it the right way to use that? The documentation is not really clear on that
thanks for your help
I'd suggest creating a global event handler to track changes. While Kentico will already do a lot of this tracking for you, you can specifically add whatever specific events you want as a global event. This will handle any changes made on the customer-facing public website, inside the Kentico UI, and in any Kentico API calls.
In your custom global event handler, you can check for different types of events based on the object and the CRUD activity. For instance something like this:
using CMS;
using CMS.CustomTables;
using CMS.DataEngine;
using CMS.DocumentEngine;
// Registers the custom module into the system
[assembly: RegisterModule(typeof(CustomInitializationModule))]
public class CustomInitializationModule : Module
{
// Module class constructor, the system registers the module under the name "CustomInit"
public CustomInitializationModule()
: base("CustomInit")
{
}
// Contains initialization code that is executed when the application starts
protected override void OnInit()
{
base.OnInit();
// Assigns custom handlers to events
DocumentEvents.Insert.After += Document_Insert_After;
}
private void Document_Insert_After(object sender, DocumentEventArgs e)
{
if (e.Node.ClassName.ToLower() == "your.classname")
{
// create an event to log to a custom module table or a custom table so it's not logged directly in the Kentico Event log
CustomTableItem item = new CustomTableItem("customtable.name");
item.SetValue("ItemEventType", "Create document");
item.SetValue("ItemEventCode", "Your event code");
item.SetValue("ItemEventUserID", e.Node.DocumentModifiedByUserID);
item.SetValue("ItemEventUrl", e.Node.NodeAliasPath);
item.SetValue("ItemEventName", e.Node.DocumentName);
item.Insert();
}
}
}
This is a simple example of when a document is created. You don't have to check the page type's classname if you don't want to. You can also include a global event handler for any "object" like a cms_class object, just use that definition in your code <name>Info.TYPEINFO.Events.<eventtype>. This is not limited to any object, you can track transformation updates, page type field modifications, etc. You just need to know the object name/type and write code around it.

How to use WaitForActivity in Visual Studio workflow for SharePoint?

I am creating Visual Studio Workflow for SharePoint and want to use activity 'WaitForActivity' in my code, that will check one property of workflow item if its not set then it will pause the execution and as soon as this property set, continue the execution of workflow.
If I use 'WhileActivity' for same then only one item shows WF status "in progress" and other items is in "Starting" state.
So how do I add 'WaitForActivity' in my workflow as there is no such activity in visual studio 2013 toolbox.
What I want to do in 'WaitForActivity' code is as below
private void CheckForField(object sender, EventArgs e)
{
SPListItem item = workflowProperties.List.GetItemById(workflowProperties.ItemId);
if (item[FieldName] != null)
{
isPropTrue = (bool)item[FieldName];
}
}
If you're not using any of the out of the box workflow tools and you're just writing your own code, I think you'll have to either put in a delayActivity that sleeps for x amount of time, checks the item and then either goes back to sleep, acts or ends the workflow based on whatever criteria.

Orchard CMS: How to cancel a remove event

I have created some code to disallow deletion of a Content Item if that item has any localized Dependencies. To do this I created a new "extension" interface and (default)class within Orchard.Framework.ContentManagement, and then created a new class within the Orchard.Localization modul, using the SuppressDependency attribute. It returns a simple Boolean value based on a query to see if there are any ContentItems that list the current item as their MasterContentItem
This is called from the AdminController within Orchard.Core.Contents, and if it returns true then I add a message and redirect to the returnUrl, otherwise the removal continues as normal.
All of this is working perfectly.
HOWEVER, I would like to refactor this to take advantage of the existing infrastructure with IContentManager and add a Removing() method to the LocalizationPartHandler.
My question is - is it possible to "cancel" the remove action based on output of ContentHandler invoked earlier...
As mentioned in my comment I'm not completely sure as to what you want to accomplish, but my guess is that you want to create your own module and within that module create a Handler implementation in which you do your thing...
From what I understand is that you want to hook into the Remove event lifecycle. Handlers provide the OnRemoving which executes before the item is removed. I'm not an expert on handlers and their extension points and how you could cancel the event, but my guess is that you want to implement the following:
public class YourCustomHandler : ContentHandler {
public YourCustomHandler(IYourCancelService yourCancelService) {
OnRemoving<LocalizationPart>((context, part) =>
yourCancelService.CancelRemoveEvent(context));
}
}
Read this for more info on handlers: http://docs.orchardproject.net/Documentation/Understanding-content-handlers

GXT custom event handler code executes multiple times

I have implemented MVP pattern in my GXT project. The system registers customers as part of it function. Also the system user can search for the registered user providing the id.
i have added an OnClick event to the "search customer" button.
/* On click search button */
view.getBtnSearch().addListener(Events.OnClick, new Listener<BaseEvent>() {
#Override
public void handleEvent(BaseEvent be) {
eventBus.fireEvent(new CustomerRegistrationTabSelectionEvent(0, false));
eventBus.fireEvent(new CustomerFetchEvent(view.getValueCustSearchParameter(), view.getValueCustSearchValue(), true));
}
});
The CustomerRegistrationTabSelectionEvent does select the relevant tab and enables other tabs. Thats all it does.
Here is the handler for the custom event CustomerFetchEvent.
eventBus.addHandler(CustomerFetchEvent.TYPE, new CustomerFetchEventHandler() {
#Override
public void fetchCustomer(CustomerFetchEvent event) {
searchCustomer(event.getParameter(), event.getParameterValue(), event.isOpenFirstTab());
}
});
The issue is the search customer method is executed multiple times and if there is a invalid search the error message dialog shows multiple popups. Within the searchCustomer method i call for service which fetch me the customer data or show the popup error message if the search is invalid.
im using GXT 2.2.5 and JRE 1.6.
Could anyone help me in finding out why the code is executed multiple times?
Added Later:
When i run the application first time the code is only executed only once, therefore only 1 popup. Then i logout of the system and log in again (navigating to the same page where the "search customer" button exists.) and the code is executed twice. Likewise equal to the number of times i create/navigate to the particular page, the code executes. Is it actually adding the event handler code without removing the last one every time i recreate the page?
Yes, it seems that 'addHandler' adds handler multiple times, but stores previous context. Your code should add handlers only once, on initialization phase. You can check the number of handlers with 'getHandlerCount' method.
Ya. I fixed it!Here is the solution Unbinding presenters necessary in GWT
U can read more here. http://draconianoverlord.com/2010/11/23/gwt-handlers.html
what happened actually was, the presenter objects where i have registered with HandlerManager to receive events were not garbage collected. Because though i remove the reference to the presenters still the HandlerManager holds a reference to those objects. So every time i kept on creating new presenters on top of the old presenters of the same class. so a event is listened by multiple objects of the same class. so u need to ensure that the unused presenters are garbage collected by removing the registered handlers
in HandlerManager.

Handling event when approving a document

In SharePoint,
using an event receiver, how do we find out when a user has approved a document in a document library?
I would think it should be captured in ItemAdded or ItemAdding event.
Any ideas?
Thanks.
ItemUpdated is the event receiver to use, unless you want to "override" the approval (and maybe keep the item unapproved) - in this case you should use the ItemUpdating.
To check if the item is approved you could try this code:
public override void ItemUpdated(SPItemEventProperties properties)
{
if (properties.ListItem["Approval Status"] == "Approved")
//Do Something
}
Hope it helps

Resources