Stopping the publish flow in an event or disabling the publish button - c1-cms

I wondering if it's possible to stop the publish flow in an event.
I want to check some properties in the code-behind before I let the user publish the object.

You can use the static DataEvents<T> class which has a OnStoreChanged event you can hook into.
Example use from the api page:
DataEvents<IMyDataType>.OnStoreChanged += new StoreEventHandler(DataEvents_OnStoreChanged);
...
void DataEvents_OnStoreChanged(object sender, StoreEventArgs storeEventArgs)
{
if (!storeEventArgs.DataEventsFired)
{
// an external update event happened - DataEvents_OnBeforeAdd not fired
// here a complete cache flush could be done
}
}
If you care about page publishing you would have to use DataEvents<IPage> and check the StoreEventArgs for the PublicationScope which should tell you whether this was a publishing event or not.
From the documentation of DataEvents<T>.OnStoreChanged:
This event is fired after changes has happened to the Composite C1 data store. This may be atomic actions or a larger change to the underlying data store. The StoreEventArgs class describe the change in broad terms, including a flag indicating is detailed data event have been raised or not. You can use this event as a simple way to react to data changes (like clearing a cache) or you can mix this with atomic data events (add, delete, update) to make a build a more advanced cache. You should listen to this event in order to support scale out across multiple servers, since this event is meant to be signaled when changes happen on another server. In such situations detailed data events will not fire on other machines.
If you care about exactly what data was changed in the event, you have to use the other events of the DataEvents<T>class like OnAfterUpdate and get this information from the DataEventArgs.

Related

In CQRS with multiple databases, should I call database functions inside Command or inside repositories?

I'm using cqrs pattern with multiples databases (one for query and another for search). Should I put the insert inside Repository
CommunityRepository{
Add(Community community){
Database1.Insert(community);
Database2.Insert(community);
}
}
and then:
CommunityCommands{
Handler(AddCommunityCommand community){
communityRepository.Add(community);
}
or should i put this in Commands, like this:
CommunityCommands{
Handler(AddCommunityCommand community){
db1.Insert(community);
db2.Insert(community);
}
or maybe something like this, using the main repository + database2
CommunityCommands{
Handler(AddCommunityCommand community){
communityRepository.Add(community);
db2.Insert(community);
}
I would do neither of those options as you'd be basically coupling the Command and Query immplementations.
Instead, publish events from the Command side, like OrderPlacedEvent and subscribe to them from the Query side. This not only allows you to separate the implementations of the Command and Query sides, but it will also allow you to implement other side effects of the events without coupling the code from the multiple features (eg. "when an order is placed, send a confirmation email").
You can implement the pub/sub synchronously (in process) or asynchronously (with a messaging system). If you use messaging, note that you'll have to deal with eventual consistency (the read data is slightly behind the write data, but eventually it catches up).
refreshing the Query Models should be handled in an offline operation. You should do something like this:
process your Command logic (whatever it is)
right before your Command handler returns, send an Event to a message bus
then in a background service you can listen to those Events and update the Query side.
Bonus tip: you can use the Outbox pattern to get more reliability. The idea is to store the Event messages in a table on your Write DB in the same transaction as your previous write operation, instead of sending them directly. A background service would check for "pending" messages and dispatch them. The rest is unchanged.

Why is the IContentEvents.LoadedContent event fired multiple times for a page?

I've added an event handler for the LoadedContent event. I'm a bit surprised that the event seems to fire multiple times for a page during a single load. Why does that happen?
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
ServiceLocator.Current.GetInstance<IContentEvents>().LoadedContent += this.EPiServerApplication_LoadedContent;
}
EDIT
I'm using EPiserver 8.
With "a singe load" I mean going from DOPE mode to edit mode for a page that is a child but has no children. Last time I counted the event fired 17 times for that page.
The LoadedContent event is fired every time Get/TryGet on the IContentLoader (or IContentRepository) is called. This happens regardless if the data is loaded through from the cache or from the database.
As these APIs are used by many separate code branches, especially in edit mode, this event will be triggered multiple times just as you have found. Normally this should not be anything that you need to be worried about unless of course you are doing something resource intensive in your event handler.

Detecting async function calls completion in silverlight

Say,there is a requirement that a customer object is loaded from the db to a silverlight application, so that the customer details are shown in the UI. We need to detect if the user is changing any data in the UI.
We are listening to property changed notifications from the view model. However, when the notifications are result of property change as part of the loading process we have to discard it.
class CustomerLoader
{
Helper helerobj;
Address addressobj;
Profile profileobj;
void LoadFromDb()
{
helperobj.Load();
addressobj.Load();
profileobj.Load();
//start listening after the loading finished
this.propertychanged += new PropertyChangedEventHandler(handlepropertychanged);
}
The trouble with this is the inner objects might be calling asynchronous functions which might set properties. So by the time we started the property change listening, the loading might not have been finished.
We need to know when the loading is actually done. As of now we are asking the developers who are developing the inner object classes to accept a callback in the parameter which they should call when the function is finished.
Is there any other way to do it?
You want nothing but a really classic asynchronous objet loading.
So yes, the only solution is to ask developers working on the loading to propose an asynchronous function. Now you hav several solution to achieve asynchronicity in Silverlight.
You could either provide a callback as you do, or use async and await to manage your asynch task as explain here: http://10rem.net/blog/2012/05/22/using-async-and-await-in-silverlight-5-and-net-4-in-visual-studio-11-with-the-async-targeting-pack

ADF lifecycle phases difference

Difference between ADF initContext and prepareModel,since both preparing data by executing buisness service making it available through binding container which is a Map object.
ADF initContext and prepareModel,since both preparing data by executing buisness service
This is not quite correct. The initContext sets up the BindingContext, which ensures the content of DataBindings.cpx is initialized and the binding container for the page to be prepared. The prepareModel is an execution point for data queries.
The other execution point, as Timo's answer shows, is PrepareRender. Recommendation though is to keep the iterator default setting, which is "deferred" in which case only those iterators are refreshed and queried that have UI dependency.
The ADF model life cycle phases:
initContext sets up the life cycle, working out what PageDefs to load.
prepareModel creates the bindings object and adds it to the HTTP request. Parameters are also evaluated at this point.
applyInputValues processes the values posted from the page and builds up an internal list of bindings to update and methods to execute as required.
validateInputValues applies the client-side validators to the list of updates presented by the applyInputValues phase. These validators are defined as nested f:validator and af:convertNumber components within an input component.
processUpdateModel sends the validated changes to bound objects to the model layer.
validateModelUpdates manages validation errors from the Model layer.
processComponentEvents processes any listeners and action events queued up from the applyInputValues phase.
metadataCommit manages part of the runtime customization capabilities of the framework.If the user has customized the page in some way such as moving components on the screen or adding in task flows via WebCenter, then those personalizations to the screen are saved away to the metadata repository (MDS) at this point.
prepareRender is the last phase to execute before the page is displayed.
Note that in some situations (such as a modal dialog), the following code will not necessarily fire after the page has been rendered:
public void afterPhase(PagePhaseEvent pagePhaseEvent) {
if (pagePhaseEvent.getPhaseId() == Lifecycle.PREPARE_RENDER_ID) {
injectRedirect();
}
}
This prevents the server code from being able to examine the af:document immediately after the document is rendered. For example the following will fail because there is no document available:
return context.getViewRoot().getChildren().get(0).getClientId().equals("doc0");

nHibernate: Reset an object's original state

I have a very basic query. I am using WPF Binding to edit a object which is loaded by a ISession. If somebody edits this object in the form, because of two way binding and a stateful session, whenever I close the session, changes to the object made in the form are stored back in the database. Which is the best way to avoid this?
The methods I know:
Shadow copy the object and use the copied object as the DataContext (the method I am using as of now).
ISession.Clear
Use IStatelessSession.
Is there any way to reset the object to it's original form before closing the ISession?
If you look here: http://nhforge.org/wikis/howtonh/finding-dirty-properties-in-nhibernate.aspx
It is an example of finding dirty properties. NHibernate internally tracks a persistent object's state by way of the EntityEntry object.
This is useful for you, because with a little modification to the method above, you're able to get old values back ... which you can use to reset the properties.
As for closing your session causing the object to be flushed to the database, you can set the session FlushMode to FlushMode.Never. This will mean no database sync occurs until you call Session.Flush().
Alternatively, you can hook into IFlushEntityEventListener to reset the object state. There are a reasonable examples of using the NHibernate event system on google.
See Managing the caches on NHibernate Forge:
When Flush() is subsequently called, the state of that object will be synchronized with the database. If you do not want this synchronization to occur or if you are processing a huge number of objects and need to manage memory efficiently, the Evict() method may be used to remove the object and its collections from the first-level cache.
I think that sounds like what you want.
I would suggest the use of transactions. You just rollbackthe transaction if that is the case? what do you think?

Resources