Code Generator

Blog
Code Generator
Thursday, September 15, 2016PrintSubscribe
Calculating Values with C#/Visual Basic Business Rules

It is a common requirement for forms of the application to feature a custom calculation or operation that must be triggered by the user pressing a button visible on the screen.

For example, let’s use the Orders page of the Northwind sample project. It may be useful to have an action that will mark the order as shipped by populating the Shipped Date field, and setting a default value for Freight if it has not been specified.

The orders form has a "Mark as Shipped" button.

The first step is to add an action to the form scope that the user will be able to press to trigger a business rule.

Start the Project Designer. In the Project Explorer, switch to the Controllers tab. Right-click on “Orders / Actions / ag2 (Form)”, and press New Action.

Adding a new action to the form of Orders controller.

Set the following properties:

Property Value
Command Name Custom
CommandArgument MarkAsShipped
Header Text Mark as Shipped
When Last Command Name Edit

Press OK to save the new action.

Next, let’s create a business rule that will perform the calculations. Right-click on “Orders / Business Rules” node, and press “New Business Rule”.

Adding a new business rule to Orders controller.

Specify the following values so that the business rule will be triggered by the action created above.

Property Value
Type C# / Visual Basic
Command Name Custom
Command Argument MarkAsShipped
Phase Execute

Press OK to save the business rule. On the toolbar, press Browse to regenerate the application and ensure that the rule file is created.

When generation is complete, press “Edit Rule” on the action bar. This will open the business rule in Visual Studio.

Replace the contents of the file with the following code.

C#:

using System;
using System.Data;
using MyCompany.Data;
using MyCompany.Models;

namespace MyCompany.Rules
{
    public partial class OrdersBusinessRules : MyCompany.Data.BusinessRules
    {
        
        /// <summary>
        /// This method will execute in any view for an action
        /// with a command name that matches "Custom" and argument that matches "MarkAsShipped".
        /// </summary>
        [Rule("r100")]
        public void r100Implementation(OrdersModel instance)
        {
            instance.ShippedDate = DateTime.Now;
            if (!instance.Freight.HasValue || instance.Freight == 0)
                instance.Freight = 13.5m;

            PreventDefault();
        }
    }
}

Visual Basic:

Imports MyCompany.Data

Namespace MyCompany.Rules

    Partial Public Class OrdersBusinessRules
        Inherits MyCompany.Data.BusinessRules

        ''' <summary>
        ''' This method will execute in any view for an action
        ''' with a command name that matches "Custom" and argument that matches "MarkAsShipped".
        ''' </summary>
        <Rule("r113")>
        Public Sub r113Implementation(instance As OrdersModel)
            'This is the placeholder for method implementation.
            instance.ShippedDate = DateTime.Now
            If Not instance.Freight.HasValue OrElse instance.Freight = 0 Then
                instance.Freight = 13.5D
            End If
            PreventDefault()
        End Sub
    End Class
End Namespace

The code will set the ShippedDate field to the current date and time. It will then check if Freight has a value, and if the value is equal to 0. If so, then the Freight will be set to the decimal number 13.5. Finally, PreventDefault() is called in order to prevent the form from navigating back to the grid.

Save the file, and refresh the web browser. Navigate to Orders page and edit a record. Notice that the “Mark as Shipped” action is now available. Pressing this action will now populate the Shipped Date with the current date and time. If the Freight field was empty, then it will be set to $13.50.

Pressing the "Mark as Shipped" button has set the value of both ShippedDate and Freight fields.

Thursday, June 9, 2016PrintSubscribe
8.5.8.0 Has Landed! New Form Rendering Engine, Advanced Lookup Input, Calendar Input, Data View Fields, Tiny Density, Save and New

The long awaited release 8.5.8.0 is here! Originally intended to be released in March of 2016, a shift in strategy has resulted in this release coming out in June. We greatly appreciate everyone’s patience, and hope that we find the result to be rewarding for everyone.

Form Rendering Engine

The biggest change in this release is an overhaul of the Form Rendering Engine. One of our biggest complaints for Touch UI was the lack of customizability of the form. The original implementation of forms provided for limited capability in ordering data fields. Categories were used to group data fields into new rows, columns, and tabs.

In response to these comments,we have added the ability to define HTML templates that allow precise positioning of data fields and custom content into the form. A simple example can be seen below.

Example of custom layout template in Touch UI.

These HTML templates will be placed under the ~/Views folder of your project. When loading a view, the application framework will attempt to find the file “[Controller Name].[View ID].html”. If not found, it will generate a default template.

A snippet from the template can be seen below:

<div data-layout="form">
    <div data-container="column" style="width:50%">
        <div data-container="collapsible" data-header-text="Order Information">
            <div data-container="row">
                <div data-control="description">This is the order information.</div>
            </div>
            <div data-container="row">
                <span data-control="label" data-field="CustomerID">CustomerID</span>
                <span data-control="field" data-field="CustomerID">[CustomerID]</span>
            </div>
            <div data-container="row">
                <span data-control="label" data-field="EmployeeID">EmployeeID</span>
                <span data-control="field" data-field="EmployeeID">[EmployeeID]</span>
            </div>...

The entire template must be wrapped in a data-layout element, and various different data-container elements are available for easy positioning of elements. Rows can be used to automatically position fields. It is always possible to use your own elements and position items manually. More documentation on this feature will be coming soon.

These layouts work perfectly well on mobile devices, too.

Example of custom layout template in Touch UI on a small screen.

In order to make the process of developing form templates easy, a visual Form Designer will be included in future releases.

The engine utilizes our new Universal Input API in order to react to user clicks and key presses. When the user clicks on a label or field, the API will find and build the relevant input control in order to handle that field. When the user leaves the field, all values that show that field value will be updated. The API handles Tab, Shift+Tab, Up, Down, Left, Right, Enter, Shift+Enter keys in order to move between fields.

Lookup 2.0

With the new Form Rendering Engine, we decided to overhaul the lookup input control to allow your users to get their work done easier and faster. The new lookup allows the user to type in their search query, and a suggestion list will automatically be loaded. Use arrow keys to navigate up and down in the list. Press Enter on your keyboard to select an option.

The user can click on the arrow to the right of the field to navigate to the lookup view.

New lookup in Form Rendering Engine animation.

The user can also press Ctrl+Space to activate the list. From there, the user can create a new lookup record, or jump to the lookup view by pressing “See All”.  “Ctrl+Enter” will also activate the lookup view.

Client-side data caching and filtering is employed in order to ensure that performance is top-notch.

Calendar Input

Dates have always been a difficult data type to work with. Every browser implements native input differently, some working better than others. Rather than compromising in order to utilize the native input of every browser, a new Calendar Input has been developed. This input control is an extension of the calendar sidebar filter component, which also includes the upgrades.

New Calendar Input in Form Rendering Engine animation.

The input will be activated when the user focuses on the field. Selecting a day in the month will set that date. The user can drag or use the arrow buttons to move between different months. Clicking on the header will allow the user to select the month or year.

If the data field also renders time, a clock will be rendered. The user can click on an area in the clock to set the time. Clicking on the hour or minute part of the header will allow changing that part of the time. Clicking on AM/PM will toggle the time of day.

The user will continue to be able to manually edit the value in the input control.

If the input is activated on a very small screen or mobile device, the Calendar Input will be displayed in the center of the screen. The user must click “OK” to save the new value, “Cancel” to close the popup, or “Clear” to reset the value.

Calendar Input on small screens will cover input and show OK, Cancel, Clear buttons.

Notice that days that contain data in the month are bold. Hovering over the day will reveal a count of records on that day. The client library makes asynchronous requests to pull the data and caches it on the client. If performance is a concern, this feature can be disabled by tagging the data field “calendar-input-data-none”.

Data View Fields

In the past, Code OnTime users needed to configure pages with multiple data views in order to display lists of data related to the master record. This process led to a disconnect between the data and presentation layers of the application.

Release 8.5.8.0 changes the paradigm. A new field type has been introduced, “DataView”. This will allow users to embed lists of records directly into the forms of master records. This change brings controllers more inline with how users would intuitively understand business objects.

Simply define a field of type “DataView”, point to the correct controller, specify the filter field, and create a data field to bind it to the form. All pages that refer to that form will now reveal relevant child records.

Data View field example.

The traditional method of defining child data views still works. This can be used for child data views that should only be displayed on certain pages (or define another view that excludes the data view field).

Future releases of the app generator will allow users to perform inline editing of child records at the same time that the master record is being modified.

Grid Upgrades

This brings us to the new and improved grid. In previous releases, it was difficult to set the size of grid columns to match up with the intended look and feel. Release 8.5.8.0 has made the grid sizing process more transparent.

The grid will now use the exact size of each data field in columns when allocating space. If there are no columns defined, then the columns will be set to 2/3s of the length of the field, or various preconfigured lengths depending on the type of the field.

In order to make the client library more intelligent and require less involvement of the user, a new feature has been added to the grid – “Fit To Width”. This will automatically shrink the grid columns to fit the screen, down to a certain limit. The space allocated to each column is equal to the proportion of “columns” that field was assigned. This feature is automatically enabled for every grid. If the behavior is undesired, the data view can be tagged “grid-fit-none” to disable the functionality.

The width of the grid may surpass the width of the page – the user will then be able to drag the grid left and right to bring different columns into view. Touch input is now supported for dragging.

If a column is too small or big to see the data, the user can click and drag the divider between columns in order to resize.

Animation of grid dragging and column resizing.

Future releases will offer the ability to reorder the columns on the client.

“Tiny” Density

Touch UI applications offer several different display densities in order to fit the needs of every user. The smallest size, Condensed, was still larger than Desktop UI. Therefore, we are introducing “Tiny” display density, which uses the same font and font size of the desktop.

The picture below compares “Comfortable” and “Tiny” display densities.

Orders form with 'Comfortable' display density.    Orders form with 'Tiny' display density.

Business Object Model and Data Access Objects

Code business rules in previous releases of Code OnTime app generator would list each field in the parameters of the method. Controllers with over a hundred fields would result in sprawling and ungainly method signatures. To update a data field for the client, it was necessary to call the UpdateFieldValue() method. See an example of legacy code below.

using System;
using System.Data;
using MyCompany.Data;

namespace MyCompany.Rules
{
    public partial class OrderDetailsBusinessRules : MyCompany.Data.BusinessRules
    {
        [Rule("r100")]
        public void r100Implementation(int? orderID,
            string orderCustomerID,
            string orderCustomerCompanyName,
            string orderEmployeeLastName,
            string orderShipViaCompanyName,
            FieldValue productID,
            string productProductName,
            string productCategoryCategoryName,
            string productSupplierCompanyName,
            FieldValue unitPrice,
            short? quantity,
            float? discount)
        {
            UpdateFieldValue("Quantity", 1);
        }
    }
}

Release 8.5.8.0 will now generate data model objects for each controller that has a code business rule, and will pass this object as a parameter to the method. The setters for each property of the data model object will update the corresponding field on the client side.

using System.Data;
using MyCompany.Data;
using MyCompany.Models;

namespace MyCompany.Rules
{
    public partial class OrderDetailsBusinessRules : MyCompany.Data.BusinessRules
    {
        [Rule("r100")]
        public void r100Implementation(OrderDetailsModel instance)
        {
            instance.Quantity = 1;
        }
    }
}

The new business rule format is vastly easier to read and understand, even for non-professional C# or Visual Basic developers.

Legacy business rules will continue to function as they did before.

Release 8.5.8.0 no longer offers a way to enable data access objects globally. The developer will need to enable data access objects on each controller by enabling the “Generate Data Access Objects” checkbox. These objects will extend the business object models. Models and data access objects will now be stored under ~/App_Code/Models folder.

Miscellaneous

These are just some of the new features in release 8.5.8.0. A more comprehensive list can be seen below:

  • Fields now have the option to be set as “Virtual”. These fields will never be included in Insert or Update queries, but are still editable by the user and can be read and manipulated in business rules. Developers no longer need to mark fields as “not modified” in rules in order to use custom fields.
  • Controllers can now be generated with “Save” and “Save and New” in create forms. By default, new applications will have this enabled by default. It can be toggled with the “Use ‘Save’ and ‘Save and New’ in forms” checkbox in the Features page of the Project Wizard.
  • Vast performance enhancements in page loading, button clicking, form opening, grid rendering and dragging, calendar rendering and dragging. HTTP requests are now smaller and data is cached when possible.
  • Re-selecting a record in the form after creating a record will no longer go back to the grid before loading the edit form. This results in significantly faster workflow when inserting multiple records.
  • Support for Report Viewer 2015.
  • Touch gesture support for Drag & Drop API – tested with Surface Pro 4, iPhone 6 Plus, iPad Pro, Nexus 5x, S7 Edge. This API is used in calendar, grid, calendar input, and panels.
  • Model Builder Tooltip API has been ported to Touch UI.
  • “Borrowed” fields defined in data models will be copied when the lookup value is changed. These fields will now be included as read-only in the create form.
  • Changing namespace of application in Web App Factory will move data model files to correct location.
  • A grey overlay will cover the screen if the user attempts to “double” click an action while another action is executing.
  • Custom scrollbar ensures a uniform user experience across browsers and themes.
  • View templates can exclusively contain the file name of another template. The application framework will load the file with that file name.
  • The text “Loading” will be displayed when the page is loading.
  • Blob Adapters no longer require the user to be logged in when there is no membership enabled.
  • Data Text Field and Data Value Field are initialized correctly if a model exists for the lookup controller.
  • Virtual lookup fields are now correctly created when defined in the data model.
  • Removed installer dependency to .NET 3.5.
  • The web.config file will not be overwritten unless necessary to avoid the “AppDomain Unloaded” message in Visual Studio.
  • Many other minor bug fixes.

We were not able to finalize some of the features that we desired to include in this release, due to time constraints. Expect to see these features in future releases:

  • Modal forms in Touch UI.
  • Grid inline editing (Data Sheet mode).
  • Use of HTML templates to define Grid/List/Card layouts.
  • Swipe left/right action group. Actions placed in this action group will be revealed when user performs the relevant gesture in the grid.
  • Promoted action group. Actions placed in this action group will be revealed when user clicks on the floating promo button at the bottom of the screen.
  • Sidebar will be rendered in the left menu panel when the screen is small or sidebar is disabled.
  • Revealing mini calendar under Calendar mode selector when sidebar is not visible.
  • Reordering of grid columns via drag & drop. The order will be saved in the browser cache.
  • Support for Azure 2.9.
  • “Bucket” lookup will allow selecting multiple items from the lookup view.
  • Rich Text Editor in Touch UI.
  • Visual Form Designer.
  • Multi-day events in Calendar.
Tuesday, December 15, 2015PrintSubscribe
Getting Started with Model Builder

Code On Time release 8.5.6.0 introduces Model Builder – a new way to build the app you want.

In the past, applications created with Code On Time created a baseline for every entity in the database, and tried to estimate the best configuration for every page, controller, and application component. A frequent complaint about the previous versions about the app generator is the lack of ability to control this automatic process. In response to these complaints, we have included a new feature, designed to give Code On Time users more control over the application development process.

The Model Builder allows developers to design a data model for each and every database entity used by the app generator. They can pick and choose fields to include in the model, define or create foreign key relationships, and even import fields from several levels away easily. Names and labels can be easily changed, formatting can be applied globally, and sorting and filtering can be applied to form a business entity.

The Model Builder is now the first step for the creation of any Code On Time premium database app.

See an example of the default data model for Order Details table of Northwind database.

example of the default data model for Order Details table of Northwind database

In addition to Model Builder, the following noteworthy bug fixes and improvements have been added to release 8.5.6.0:

  • Support for Visual Studio 2015
  • Support for Azure 2.7 and 2.8
  • Support for .NET 4.6
  • CodeMirror integration in Model Builder and Project Designer
  • Charts in Touch UI now support color tags. Specify a list of colors, like so: "pivot1-row1-colors:'red, green, blue'".
  • Added tag “calendar-mini-disabled” to disable the mini calendar on the sidebar
  • Controller XML files ending with “.baseline.xml” in the Controllers folder will be used as a baseline controller, ignoring the data model.
  • Fixed scaling problem on high DPI devices.
  • Touch UI inputs now show a single line below the input.
  • Neutral cultures are now included in the list supported by app generator
  • Boolean fields will show check glyphicon in Touch UI when in read-only mode
  • Many more minor bug fixes

Working with the Model Builder

After entering the database connection string, a list of database entities will be listed. Select an entity to start building a data model.

List of database objects listed that can be used to create data models.

The Model Builder will open.

The default data model for Products table.

Adding additional fields to the data model is simple. Check the box next to a column to include the field.

Including "Country" field in the data model.

Fields defined with a custom SQL formula are also simple to add. Click the “Add Formula Field” button on the toolbar to get started.

Adding a custom SQL formula field to the data model.

Enter a name for the field in the first textbox. Enter the formula in the text area.

Adding a custom SQL formula field to the data model.

Use “Ctrl+Space” to see a list of columns. Fields can also be dragged from the diagram to be added to the formula.

Auto complete option in the SQL formula field.

Reorder fields in the model by dragging the Field column to the correct position.

Reordering fields via drag and drop.     Reordering fields via drag and drop.

Field labels and options can be changed by clicking in the cell. The following shortcuts can be used to quickly and easily navigate between the different cells:

  • If mouse cursor shows text, click to change
  • F2 to Select All/End
  • Left/Right moves between cells in row
  • Tab/Shift+Tab to move between cells
  • Up/Down to move up down
  • Enter/Shift+Enter to move up down
  • Esc once will restore original if changed, Esc twice will exit edit mode
  • Ctrl+Enter will save, stay editing

Changing labels in the data model.

Sorting can be added to the data model by entering the Sort Type and Sort Order.

Changing sorting in the data model.

The Query tab shows the command for the data model.

The Query tab shows the command for the data model.

The Data tab shows the output of the command. By default, Raw Data mode is on. This will show all primary and foreign key fields, and show native value formatting from the database.

The Data tab shows sample output of the data model's command.

Disabling Raw Data will hide primary and foreign keys, and apply formatting.

Disabling Raw Data mode will hide keys, and apply formatting.

The Labels button will replace field names with labels.

Enabling "Labels" button will replace field names with labels.

Click Save to persist the new data model. Proceed to generate the application. A page has been added, showing a grid of products, as defined by the data model.

A list of products, as defined by the data model.

The user can also switch to list view.

A list of products, as defined by the data model.

Automatic charts have also been created.

Charts automatically created for Products.

You can edit existing products or create new ones. Notice, however, that the Supplier ID and Category ID have not been configured as lookups.

Products edit form, with Suppliers and Categories not defined as data models.

Let’s add Categories and Suppliers data models. Go back to the generator and create a data model for Categories. Notice that these two tables that are referred to are already suggested.

Creating data models for suggested database entities.

Create the data model for Categories.

Creating data model for categories.

Create a data model for Suppliers. Be sure to sort by CompanyName and disable the HomePage field.

New data model for Suppliers, sorted by CompanyName and HomePage field disabled.

Regenerate the project. Be sure to refresh when prompted. Notice that Supplier and Category are now rendered as lookups.

Products edit form with Supplier and Category models defined.

Activating the Supplier lookup will open a list of suppliers.

Supplier lookup

Activating the Categories lookup will show a list of categories to select.

Categories lookup.

Let’s create a second data model for Products, that only shows products from North America. There are two ways of creating a copy of a data model – saving a copy of an existing model, or creating a new model, listed under “Defined” section.

Creating a data model for an entity with an existing data model.

Let’s create a copy. Open the Products data model, and change the name to “NorthAmericanProducts” by typing in the name in the top-right corner.

Changing the name of the model to "NorthAmericanProducts".

Let’s add a filter to the new model. Click the “Add Filter…” button on the toolbar.

Adding a filter to the model.

Enter the filter in the text area.

Entering a filter.

In addition, sort the ProductName in descending order.

Sorting the model by ProductName in descending order.

The Query tab will show the new command.

The new command of the data model.

The Data tab shows that the sorting and filtering was a success.

The Data tab showing the output of the command.

To save the data model as a copy, activate the dropdown next to “Save”, and press “Save a Copy”.

image

Proceed to generate the application. Notice that another page has been added to the sitemap. This page is a Single Page Application created to handle products from North America.

The new page shows products from North America.

Virtual Connections

One of the most powerful aspects of the Model Builder is the ability to define virtual primary and foreign keys. Let’s create a data model using the view Alphabetical List Of Products.

Creating a data model for "Alphabetical List of Products".

The application framework is unable to perform any CRUD operations on a business entity until a primary key is defined. Let’s create a virtual primary key by right-clicking ProductID and pressing Set Primary Key.

Setting the virtual primary key of the Alphabeticallistofproducts data model.

The spec “VPK” will be added to the first column of the diagram.

The ProductID field has been specified as the primary key of the model.

Notice that because Alphabetical List Of Products is a view, foreign keys are not known, and values from these foreign key relationships cannot be included until a virtual foreign key is defined.

On the toolbar, click the “Add Table” button.

Adding a table to the diagram.

The field list at the top of the Model tab will be replaced with a list of database objects.

Adding a table from the list of available tables.

Drag the “dbo.Suppliers” table onto the diagram. Rename the alias of Suppliers to “Supplier” by clicking on the header of the new table in the diagram.

Renaming the new table to "Supplier".

Then, drag the “SupplierID” field from Alphabeticallistofproducts onto SupplierID column of Suppliers table to form a virtual foreign key. You can now check fields from the Suppliers table to include in the data model.

Including fields of Suppliers table into Alphabeticallistofproducts data model.

Sort this data model by entering “Descending” in the Sort Type of ProductName.

Sorting by ProductName.

The final result will show the inclusion of Supplier fields in the grid.

The new SPA for Alphabeticallistofproducts.

Continue to Maximizing Charts