Documentation

Creating Strongly-Typed Models

Version 1.2   |   Last Updated: 1/28/2014 (v1.2)   |  

Working with strongly-typed model objects is one of the core principles of the ZohoSharp library. The library allows clients the flexibility to work with model types that suit their needs. All of the library methods for interacting with the Zoho API will support the use of POCO model objects. The only requirement is that the Zoho fields are implemented as properties (as opposed to fields). The library provides a set of base POCO model classes with all of the default fields for each Zoho CRM module – these classes may be extended to add custom fields. Custom POCO model classes can also be used – either for built-in modules or for custom modules. If implementing custom model classes, attributes should be used to identify the Id property (see the Id Property Identification section) and other properties requiring special handling (see the Special Model Properties section). When selecting a .NET framework type for custom model properties, see the Zoho Field Type to .NET Type Mapping section for supported types and other considerations.

The ZohoSharp library provides a more advanced option for strongly-typed models by first defining an ISyncableModel interface. The ISyncableModel interface defines a set properties and methods for internal tracking of the model state (and individual property states) along with a set of dictionaries that provide insight into the model object’s property values relative to the Zoho field values and relative to the model state. In other words, it helps answer the question, “Is the local model object in sync with the Zoho data record?”

The library also provides a set of off-the-shelf model classes implementing the ISyncableModel interface along with other useful functionality (see the SyncableModelBase Models section). The following sections describe the details of the ISyncableModel interface and the SyncableModelBase derived models. Code samples are also available that demonstrate custom model implementations and customizing the provided CRM model objects.


ISyncableModel Interface

At the core of the ISyncableModel functionality is the ModelState, which indicates the state of the entire model object. The central concept of the ModelState and the ISyncableModel interface as a whole is tracking the level to which the local model object is in sync with the remote record stored on Zoho’s system. Following are the possible values for ModelState:

None
The model state is not known or is not tracked relative to the Zoho system.
New
The model object is newly created and unknown to the Zoho system.
Modified
The model object is known (or believed) to have been modified from the version on the Zoho system.
Unsynced
The model object has not been directly synced or retrieved from the Zoho system, but intended to be the same as the Zoho version (when a model object is updated/inserted to the Zoho system, but the changes are not confirmed).
Unsyncable
The model object has been updated/inserted into the Zoho system and an unsuccessful attempt has been made to confirm these updates (the values of some properties are not syncable).
Unassignable
The model object contains one or more field values that could not be assigned to their mapped properties.
Synced
The model object is the same as the Zoho version as of the last sync time (LastSyncedTime property).
Deleted
The model object has been deleted from the Zoho system.

The ISyncableModel interface also defines mechanisms for tracking the state of individual properties (PropertyState). Each property can take on property state values that are equivalent to the model state values, except applicable to the property instead of the model as a whole (when the model is in a New or Deleted state, all properties reflect the same state). Given that properties can have a mixture of states, a hierarchy is defined when declaring the entire model object with a singular state (for non-New and non-Deleted model states):

  • If any property is Modified, the model object is considered Modified, otherwise,
  • If any properties have an Unassignable state, then the model is considered Unassignable, otherwise,
  • If any properties have an Unsynced state, then the model is considered Unsynced (properties should not have a mixture of Unsynced and Unsyncable/Refreshable/Synced as the latter states indicate that a sync attempt was made), otherwise
  • If any properties have an Unsyncable state, then the model is considered Unsyncable, otherwise,
  • If any properties have a Refreshable state, then the model is considered Refreshable, otherwise,
  • The model is considered Synced (and all properties reflect the Synced state).

Once model objects are loaded with values from Zoho or values are submitted as part of an update or insert, the client doesn’t really know to what extent the local model object values match the actual data stored in the Zoho system. The ISyncableModel interface addresses this issue with the definition of a set of field/property dictionaries.

The RawFields dictionary defines a set of field data, keyed by the Zoho field name. For each field, a RawFieldData object is stored. This object contains the local model property name to which the Zoho field is mapped (if it was mapped), a FieldMappingState value which specifies the manner in which the Zoho field was matched to the model property and a raw string value representation of the field value as stored in the Zoho system. See the Field Mappings section and the Get Logic section for more information on how the Zoho fields are mapped to the local model properties. The entries loaded into this dictionary are dependent upon the library or get method settings – see the RawFieldsOption in the General Get Options section for further detail.

The UnassignableProperties dictionary, keyed by the model property names, represents field data (RawFieldData object) that could not be assigned to the matched local model property. These entries should be fairly uncommon, usually representing cases in which the string value returned from the Zoho system could not be converted to the model property type.

The UnsyncableProperties dictionary, keyed by the model property names, represents model properties that could not be synced with the Zoho system after an update or insert. The dictionary values represent the model property values as they are stored in the Zoho system. Only those property values that were delivered to Zoho as part of an insert or update (after which the Zoho system did not reflect the same values) will be considered Unsyncable and thus loaded to this dictionary. Other field values that may have changed would be considered Refreshable.

The RefreshableProperties dictionary, keyed by the model property names, represents model properties that have "refreshable" values - properties that have a more recent value retrieved from the Zoho system. The dictionary values represent the model property values as they are stored in the Zoho system.

The ISyncableModel interface also defines methods for updating the model properties with the values stored in the UnsyncableProperties and RefreshableProperties dictionaries (AssignUnsyncableValue(s) and AssignRefreshableValue(s)).

When model objects used with the ZohoSharp library implement ISyncableModel, the library methods will call the ISyncableModel methods as necessary to update the model state, property states and the property/field dictionaries.


SyncableModelBase Models

The ZohoSharp library defines a base model class, SyncableModelBase, that implements the functionality described for ISyncableModel. Unless state tracking has been disabled for a model object, the SyncableModelBase class will internally manage the model state and the property states. In addition to the ISyncableModel interface, SyncableModelBase also implements INotifyPropertyChanged, INotifyDataErrorInfo, IEditableObject and IValidatableModel. This gives SyncableModelBase and the model objects derived from it, a versatile set of functionality to manage state, UI bindings and error notification, validation and undo capability.

SyncableModelBase inherits from another base model class provided, BindableModelBase, that handles the implementation of the INotifyPropertyChanged, INotifyDataErrorInfo and IValidatableModel (see the Model Validation section) interfaces. The base implementations of INotifyPropertyChanged and INotifyDataErrorInfo allow derived models to support two-way data binding and error notification. The implementation also supports setting of the data binding properties on a different thread from the UI (as the data binding notifications must be called on the same thread as the UI). This allows the model to be updated with asynchronous operations (for which the ZohoSharp library was designed). The INotifyPropertyChanged implementation requires derived class properties to call a NotifyPropertyChanged method in the setter and allows passing a lambda expression instead of a string. Error notification is supported by passing in an external implementation of an IValidator object and calling the ValidateProperty method in derived classes.

SyncableModelBase implements the .NET framework IEditableObject interface itself to support deep cloning of itself, BeginEdit, CancelEdit and EndEdit functionality. This gives the model object undo capability. These methods must be called by the library client – the ZohoSharp library will not call these methods during the course of its interaction with the Zoho API (e.g., the library will not call EndEdit when the Zoho API is updated with model object).

SyncableModelBase also provides serialization support through the .NET framework DataContract attribute. Derived classes wishing to retain this support should specify the DataContract and DataMember attributes.

The library provides a set of base classes inheriting from SyncableModelBase with all of the default fields for each Zoho CRM module. Like the POCO model classes, these classes may be extended to add custom fields or SyncableModelBase itself may be extended to implement custom module models. If implementing custom model classes, attributes should be used to identify the Id property (see the Id Property Identification section) and other properties requiring special handling (see the Special Model Properties section). The library also provides an interim class, CRMSyncableModelBase that serves as a base for all standard CRM module records – it provides an Id property and properties for the special fields shared by most of the Zoho CRM modules. If a custom model factory is not specified (see the Model Factory section), the library will generate the SyncableModelBase derivation objects for each module by default (and will generate a CustomModuleSyncableBase object for custom modules). CustomModuleSyncableBase derives from CRMSyncableModelBase, simply adding the a Name property and a LastActivityTime property which all custom module records get by default.

When extending any of the base syncable model classes or if implementing a custom model by deriving directly from SyncableModelBase, CRMSyncableModelBase or CustomModuleSyncableBase, there a few guidelines which should be followed. Any properties which should be included with a DataContract serialization should be decorated with the DataMember attribute. The property setters should call the SyncProperty method – this is required to support the model state tracking, property change notification, error notification and validation. A code snippet (smprop) is provided to do the above automatically.

A KnownType attribute must be defined for any custom model properties that are added with a type of any custom enums, PickList derivations or MultiPickList derivations. This is required to support serialization of the UnsyncableProperties and RefreshableProperties dictionaries.

  • KnownType attributes must also be added for arrays or lists of custom enums.
  • KnownType attributes cannot be added for both an array of custom enums and a list of the same custom enums – thus, the model should only define properties as arrays or lists for a particular enum type.
  • KnownType attributes do not need to be added for nullable versions of an enum type (just for the base enum type)

No matter which type of strongly-typed objects are used, property types must be chosen that correspond to the Zoho field types appropriately. The Zoho Field Type to .NET Type Mappings section details these considerations.