Appendix A - Data Rules Pre and Post-Save IDO Extension Class Source Code Example

Creating the Assembly.

  1. In the Mongoose application, go to the IDO Extension Class Assemblies form.
    Note: In SyteLine, go to the IDO Custom Assemblies form.
  2. Take off the filter and create a record with these information:
    • Assembly Name: DRExampleUserTasks
    • Assembly Type: Build From Source
    • Language: C#
    • References: add System.Data.dll to the References string.
      In total, the References are:
      System.dll, System.Data.dll, System.Linq.dll, System.Core.dll, System.Transactions.dll, System.Net.dll, System.Web.dll, System.Net.Http.dll
    • Filename on the Assembly: DRExampleUserTasks
    Appendix A: IDO Extension Class Assemblies form
  3. Save the assembly record.
  4. Click the Source Code button.
  5. In the Filename in the Source Code area of the Assembly enter: DRExampleUserTasks.cs.
  6. Paste this code in the Code Editor:
    using System;
    using System.Collections.Generic;
    using System.Data;
    using Mongoose.IDO;
    using Mongoose.IDO.Protocol;
    using Mongoose.IDO.DataAccess;
    
    //Filename in the Source Code area in MG on IDO Custom Assemblies Form - Source Code should be: DRExampleUserTasks.cs
    namespace DRExampleUserTasks
    {
       [IDOExtensionClass( "DRExampleUserTasks" )]
       public partial class DRExampleUserTasks : IDOExtensionClass
       {
          /// <summary>
          /// IDO Data Rule Action Method (Pre-Save) - Enforces that EndDate is not earlier
          /// than StartDate. If EndDate precedes StartDate, EndDate is automatically set
          /// to the value of StartDate before the row is saved.
          /// </summary>
          /// <param name="updateCollectionRequest">The update collection request context.</param>
          /// <param name="updateItem">The individual row being updated.</param>
          [IDOActionMethod]
          public void OnEDtEarlierThanSDt( UpdateCollectionRequestData updateCollectionRequest, IDOUpdateItem updateItem )
          {
             DateTime? endDate = updateItem.Properties["EndDate"].GetNullableValue<DateTime>();
             DateTime? startDate = updateItem.Properties["StartDate"].GetNullableValue<DateTime>();
    
             if ( endDate.HasValue && startDate.HasValue && endDate.Value < startDate.Value )
             {
                updateItem.Properties["EndDate"].Value = updateItem.Properties["StartDate"].Value;
                updateItem.Properties["EndDate"].Modified = true;
             }
          }
          
          /// <summary>
          /// Example IDO extension class demonstrating a Data Rules post-save
          /// action method that sends an email using the GenericSendEmail AES event.
          /// 
          /// IDO Setup:
          ///   Add these unbound (transient) properties to the IDO:
          ///     - ToEmailAddress  (String, Updateable)
          ///     - Subject         (String, Updateable)
          ///     - Body            (String, Updateable)
          /// 
          /// Custom Assembly Setup:
          ///   Add "System.Data.dll" to the References field on the
          ///   IDO Extension Class Assemblies form.
          ///
          /// Because of ApplicationDB being used
          /// which is in the: Mongoose.IDO.DataAccess namespace
          /// using Mongoose.IDO.DataAccess; needed to be added
          /// 
          /// Data Rule Setup:
          ///   Action Type: Call Action Method Post-Save
          ///   Action Method Name: SendEmailOnSave
          /// </summary>
          [IDOActionMethod]
          public void SendEmailOnSave( UpdateCollectionRequestData updateCollectionRequest, IDOUpdateItem updateItem )
          {
             string toAddress = updateItem.Properties["ToEmailAddress"].GetValue( string.Empty );
             string subject = updateItem.Properties["Subject"].GetValue( string.Empty );
             string body = updateItem.Properties["Body"].GetValue( string.Empty );
    
             if ( string.IsNullOrEmpty( toAddress ) || string.IsNullOrEmpty( subject ) )
                return;
    
             string currentUser = IDORuntime.Context.UserName;
             string fromEmail = GetUserPrimaryEmail( currentUser );
    
             if ( string.IsNullOrEmpty( fromEmail ) )
             {
                System.Diagnostics.Trace.TraceWarning(
                   "SendEmailOnSave: No primary email found for user '{0}'. Email not sent.",
                   currentUser );
                return;
             }
    
             try
             {
                List<ApplicationEventParameter> parameterList = new List<ApplicationEventParameter>();
    
                ApplicationEventParameter parm = new ApplicationEventParameter();
                parm.Name = "EmailTo";
                parm.Value = toAddress;
                parm.Output = false;
                parameterList.Add( parm );
    
                parm = new ApplicationEventParameter();
                parm.Name = "EmailReplyTo";
                parm.Value = fromEmail;
                parm.Output = false;
                parameterList.Add( parm );
    
                parm = new ApplicationEventParameter();
                parm.Name = "EmailSubject";
                parm.Value = subject;
                parm.Output = false;
                parameterList.Add( parm );
    
                parm = new ApplicationEventParameter();
                parm.Name = "EmailMessage";
                parm.Value = body;
                parm.Output = false;
                parameterList.Add( parm );
    
                parm = new ApplicationEventParameter();
                parm.Name = "EmailHTMLFormat";
                parm.Value = "FALSE";
                parm.Output = false;
                parameterList.Add( parm );
    
                ApplicationEventParameter[] appEventParms = parameterList.ToArray();
                string result;
    
                bool success = this.FireApplicationEvent(
                   "GenericSendEmail",
                   false,
                   true,
                   out result,
                   ref appEventParms );
    
                if ( !success )
                {
                   System.Diagnostics.Trace.TraceError(
                      "SendEmailOnSave: GenericSendEmail event failed. Result: {0}",
                      result );
                }
             }
             catch ( Exception ex )
             {
                System.Diagnostics.Trace.TraceError(
                   "SendEmailOnSave: Error sending email for user '{0}': {1}",
                   currentUser, ex.Message );
             }
          }
    
          private string GetUserPrimaryEmail( string username )
          {
             try
             {
                using ( ApplicationDB db = IDORuntime.Context.CreateApplicationDB() )
                {
                   IDbCommand cmd = db.CreateCommand();
                   cmd.CommandType = CommandType.Text;
                   cmd.CommandText =
                      "SELECT ue.EmailAddress " +
                      "FROM UserEmail ue " +
                      "INNER JOIN UserNames usr ON usr.Username = ue.Username " +
                      "WHERE usr.Username = @Username " +
                      "AND ue.EmailType = ISNULL( usr.PrimaryEmailType, 'P' )";
    
                   IDORuntime.AppDataProvider.AddCommandParameterWithValue<string>( cmd, "Username", username );
    
                   object result = db.ExecuteScalar( cmd );
    
                   if ( result != null && result != DBNull.Value )
                      return result.ToString();
                }
             }
             catch ( Exception ex )
             {
                System.Diagnostics.Trace.TraceError(
                   "GetUserPrimaryEmail: Error retrieving email for user '{0}': {1}",
                   username, ex.Message );
             }
    
             return string.Empty;
          }
       }
    }
    
  7. Click OK of the Code Editor to close the form, and click the Save button.
  8. Click the Check In button and click OK past the message:
     Source control integration is currently disabled in the current configuration. The item will not be checked in to source control.
  9. Close the Source Code page using the X or close button at the top right of the page.
  10. On the IDO Extension Class Assemblies form, click the Build Assembly button on the right side.

    It should build and display the message:“Assembly compiled and updated successfully.”

  11. Click OK.
  12. Click the Check In button.
  13. Open the IDOs form and filter on the IDO: DRExampleUserTasks.
  14. Check out the IDO and populate these fields:
    • IDO Assembly Name: DRExampleUserTasks
    • Ext. Class Namespace: DRExampleUserTasks
    • Extension Class Name: DRExampleUserTasks
    Appendix A - IDO Assembly Name and Ext Class
  15. Save the IDO record.
  16. Check In the IDO.
  17. Discard the IDO Cache.
    Caution: The IDO Name and Extension Class Name must match exactly.

    When adding Custom Assembly Extension Class code, if the IDO already has some, it is better to create a New IDO, or find an IDO that does not have a Custom Assembly Extension Class.

  18. Navigate to Form > Definition > Unload Global Form Objects
    Note: This will also discard the IDO cache if View > User Preferences > Unload IDO Metadata with Forms is selected.