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.
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
:
LastSyncedTime
property).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):
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.
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.
© 2022 Jeff Williamson. All rights reserved. Privacy Policy | Terms of Service