Blog: Posts from September, 2012

Labels
AJAX(112) App Studio(7) Apple(1) Application Builder(245) Application Factory(207) ASP.NET(95) ASP.NET 3.5(45) ASP.NET Code Generator(72) ASP.NET Membership(28) Azure(18) Barcode(2) Barcodes(3) BLOB(18) Business Rules(1) Business Rules/Logic(140) BYOD(13) Caching(2) Calendar(5) Charts(29) Cloud(14) Cloud On Time(2) Cloud On Time for Windows 7(2) Code Generator(54) Collaboration(11) command line(1) Conflict Detection(1) Content Management System(12) COT Tools for Excel(26) CRUD(1) Custom Actions(1) Data Aquarium Framework(122) Data Sheet(9) Data Sources(22) Database Lookups(50) Deployment(22) Designer(177) Device(1) DotNetNuke(12) EASE(20) Email(6) Features(101) Firebird(1) Form Builder(14) Globalization and Localization(6) How To(1) Hypermedia(2) Inline Editing(1) Installation(5) JavaScript(20) Kiosk(1) Low Code(3) Mac(1) Many-To-Many(4) Maps(6) Master/Detail(36) Microservices(4) Mobile(63) Mode Builder(3) Model Builder(3) MySQL(10) Native Apps(5) News(18) OAuth(9) OAuth Scopes(1) OAuth2(13) Offline(20) Offline Apps(4) Offline Sync(5) Oracle(11) PKCE(2) Postgre SQL(1) PostgreSQL(2) PWA(2) QR codes(2) Rapid Application Development(5) Reading Pane(2) Release Notes(183) Reports(48) REST(29) RESTful(29) RESTful Workshop(15) RFID tags(1) SaaS(7) Security(81) SharePoint(12) SPA(6) SQL Anywhere(3) SQL Server(26) SSO(1) Stored Procedure(4) Teamwork(15) Tips and Tricks(87) Tools for Excel(2) Touch UI(93) Transactions(5) Tutorials(183) Universal Windows Platform(3) User Interface(338) Video Tutorial(37) Web 2.0(100) Web App Generator(101) Web Application Generator(607) Web Form Builder(40) Web.Config(9) Workflow(28)
Archive
Blog
Posts from September, 2012
Friday, September 21, 2012PrintSubscribe
Allow Nulls for Fields

When the Allow Nulls property on a field is marked as false, the client library will prevent the update or insertion of a blank value.

The application generator will set Allow Nulls to “false” for all fields based on mandatory table columns when the baseline application is constructed.

For example, the Employees table does not allow null values in First Name field, but does allow null values for Title field. An asterisk (*) is placed next to the field name to indicate required fields.

Employees edit form with First Name required field and the not required Title field.

If the value is cleared in First Name field and user attempts to save the record, the client library will prevent the update and display a message next to the field.

When the user attempts to save with a blank required field, a message will be displayed.

Let’s allow nulls in First Name and prevent nulls in Title.

Start the Project Designer. Switch to the controllers tab in the Project Explorer and double-click on Employees / Fields / FirstName field node.

FirstName field of Employees controller in the Project Explorer.

Enable Allow Nulls:

Property New Value
Allow null values. True

Press OK to save the field. Notice that the asterisk (*) next to the FirstName field node has been removed to indicate that the field is no longer required.

Double-click on Employees / Fields / Title field node.

Title field of Employees controller in the Project Explorer.

Mark the field as required:

Property New Value
Allow null values. False

Press OK to save. On the Project Designer toolbar, press Browse.

Navigate to the Employees page and edit the details of a record. The First Name field is not marked as required, but the Title is.

Employees edit form with First Name not rendered as required. The Title field is marked as required.

Clear the values from both First Name and Title fields, and try to save the record by pressing OK. A message will be displayed next to the Title field.

When a user attempts to save a blank value in a required field, the client library will display an error message.

Enter a value in Title and save again. This time the action will be passed to the server. However, the FirstName column in Employees table is still marked as required in the database. An error message will be raised by the database engine and displayed at the top of the page. Changes will not be persisted.

When the user attempts to save a blank value in a field marked as nullable in the application but required in the database, an SQL error mesage will be displayed at the top of the page.

Friday, September 21, 2012PrintSubscribe
Implementing a Custom Action

Let’s implement a custom action that will apply a discount to all line items of a specific order. Orders are stored in the table Orders, and line items are stored in Order Details.

Relationship between Orders and Order Details tables in the Northwind database.

Adding a Custom Action

First, an action needs to be defined in the action group of a data controller.

Start the Project Designer. In the Project Explorer, switch to the Controllers tab. Right-click on Orders / Actions / ag4 (ActionBar) – Edit/Delete action group node, and press New Action.

New Action context menu option for action group 'ag4' of Orders controller.

Assign the following values:

Property Value
Command Name Custom
Command Argument ApplyDiscount
Header Text Apply a Discount
When Key Selected Yes
Confirmation _controller=OrderDiscount
_title=Specify a Discount
_width=500

Press OK to save the action.

The Confirmation property references a data controller called “OrderDiscount”. This data controller does not exist in the project – we will create this confirmation data controller from scratch and have it configured to collect the Discount value from the user. The data controller will not be based on any database table or view.

Creating the Confirmation Controller

On the Project Explorer toolbar, press the New Controller icon.

New Controller context menu option on the Project Explorer toolbar.

Give this controller a name:

Property Value
Name OrderDiscount

Press OK to save.

Right-click on OrderDiscount / Fields node, and press New Field.

New Field context menu option for OrderDiscount controller.

Assign the following values:

Property Value
Name CustomerCompanyName
Type String
Length 50
The value of this field is calculated by a business rule expression.
True
Label Customer Company Name
Values of this field cannot be edited True

Press OK to save.

Add another field with these values:

Property Value
Name Discount
Type Single
Label Discount

Save the field.

Generate the app and select an order. On the action bar, press the Apply a Discount action.

Custom action 'Apply a Discount' accessible on the action bar of Orders grid view.

A modal form with two empty fields, Customer Company Name and Discount, will be displayed.

ApplyDiscount confirmation modal window with empty values in fields 'Customer Company Name' and 'Discount'.

Let’s populate Customer Company Name with the name of the company associated with the selected order and initialize Discount with the average discount of the order details.

In the Project Explorer, right-click on OrderDiscount / Business Rules node, and press New Business Rule.

New Business Rule context menu option for OrderDiscount confirmation controller.

Assign the following values:

Property Value
Type SQL
Command Name New
Phase Execute
Script
set @CustomerCompanyName = @Context_CustomerCompanyName

select @Discount = avg(Discount) 
from "Order Details"
where OrderID = @Context_OrderID

Press OK to save the business rule.

The parameter @CustomerCompanyName refers to the CustomerCompanyName field of the confirmation data controller.

The parameter @Context_CustomerCompanyName refers to the CustomerCompanyName field of the Orders data controller.

The application framework will pass the script for execution to the database engine when the action Custom / ApplyDiscount is activated by the user. The result is shown in the next screenshot.

Specify a Discount modal confirmation window with average discount.

If the user clicks OK, nothing will happen. The application does not know what to do with a “Custom” action with argument of “ApplyDiscount”.

Creating an SQL Business Rule to Handle the Action

Now that an action and controller are in place to capture the user input, a business rule needs to be created to apply the specified discount to all OrderDetails data rows associated with the selected order.

Right-click on Orders / Business Rules node, and press New Business Rule.

New Business Rule context menu option for Orders controller.

Use these values:

Property Value
Type SQL
Command Name Custom
Command Argument ApplyDiscount
Phase Execute
Script
-- apply discount to order details
update "Order Details"
set Discount = @Parameters_Discount
where OrderID = @OrderID

-- force refresh of child views
set @Result_RefreshChildren = 1

Press OK to save.

The first statement in the SQL script will update [Order Details].[Discount] column where the OrderID matches the selected order. The value of the discount is referenced by @Parameters_Discount parameter.

The second statement instructs the client library to refresh the child data views of the master data view Orders. This will cause Order Details data view to reflect the updated discount.

On the Project Designer toolbar, press Browse. Navigate to the Orders page and select an order. A list of related order details will be displayed below. Take note of the discounts of the order details.

Selecting an order from the list will reveal a list of order details related to the order.

On the action bar of Orders grid view, press Apply a Discount. The confirmation modal popup will appear, displaying the current Customer Company Name and the average discount. Enter a discount of “.25”.

Discount has been specified in the confirmation modal popup.

Press OK, and the specified discount will be applied to all records in Order Details table that belong to the selected order.

Order Details have all been updated with the new discount.

Creating “Code” Business Rule to Handle the Action

Instead of using SQL, you may also create a code business rule written in C# or Visual Basic to handle the calculation.

If you have implemented the previous SQL business rule, you will need to delete it.

Right-click on Orders / Business Rules / Custom, ApplyDiscount (Sql / Execute) - r100 business rule node and press Delete.

Delete context menu option for the previously created SQL business rule.

Right-click on Orders / Business Rules node and press New Business Rule.

New Business Rule context menu option for Orders controller in the Project Explorer.

Assign these values:

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

Save the rule. “Code” business rules do not have a script stored in the data controller definition file. A code file must be created in the project. The application generator will create an initial “empty” business rule code file as soon as the project is generated.

On the Project Designer toolbar, press Generate.

When complete, right-click on Orders / Business Rules / Custom, ApplyDiscount (Code / Execute) – r100 node and press Edit Rule in Visual Studio.

Context menu option 'Edit Rule in Visual Studio' for the code business rule.

The file will be opened in Visual Studio. The generator has created a template for the business rule. Replace the existing code with the following:

C#:

using System;
using MyCompany.Data;

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 "ApplyDiscount".
        /// </summary>
        [Rule("r100")]
        public void r100Implementation(
                    int? orderID,
                    string customerID,
                    string customerCompanyName,
                    int? employeeID,
                    string employeeLastName,
                    DateTime? orderDate,
                    DateTime? requiredDate,
                    DateTime? shippedDate,
                    int? shipVia,
                    string shipViaCompanyName,
                    decimal? freight,
                    string shipName,
                    string shipAddress,
                    string shipCity,
                    string shipRegion,
                    string shipPostalCode,
                    string shipCountry)
        {
            // This is the placeholder for method implementation.
            using (SqlText applyDiscount = new SqlText(
                "update [Order Details] " +
                "set Discount = @Discount " +
                "where OrderID = @OrderID"))
            {
                applyDiscount.AddParameter("@Discount", SelectFieldValue("Parameters_Discount"));
                applyDiscount.AddParameter("@OrderID", orderID);
                applyDiscount.ExecuteNonQuery();
            }
            Result.RefreshChildren();
        }
    }
}

Visual Basic:

Imports MyCompany.Data
Imports System
Imports MyCompany.Rules

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 "ApplyDiscount".
        ''' </summary>
        <Rule("r100")> _
        Public Sub r100Implementation( _
                    ByVal orderID As Nullable(Of Integer), _
                    ByVal customerID As String, _
                    ByVal customerCompanyName As String, _
                    ByVal employeeID As Nullable(Of Integer), _
                    ByVal employeeLastName As String, _
                    ByVal orderDate As Nullable(Of DateTime), _
                    ByVal requiredDate As Nullable(Of DateTime), _
                    ByVal shippedDate As Nullable(Of DateTime), _
                    ByVal shipVia As Nullable(Of Integer), _
                    ByVal shipViaCompanyName As String, _
                    ByVal freight As Nullable(Of Decimal), _
                    ByVal shipName As String, _
                    ByVal shipAddress As String, _
                    ByVal shipCity As String, _
                    ByVal shipRegion As String, _
                    ByVal shipPostalCode As String, _
                    ByVal shipCountry As String)
            'This is the placeholder for method implementation.
            Using applyDiscount As SqlText = New SqlText(
                    "update [Order Details] " +
                    "set Discount = @Discount " +
                    "where OrderID = @OrderID"
                    )
                applyDiscount.AddParameter("@Discount", SelectFieldValue("Parameters_Discount"))
                applyDiscount.AddParameter("@OrderID", orderID)
                applyDiscount.ExecuteNonQuery()
            End Using
            Result.RefreshChildren()
        End Sub
    End Class
End Namespace

Save the file, and refresh the web page. The Assign a Discount action will function in exactly the same way as the version with the SQL business rule.

Wednesday, September 19, 2012PrintSubscribe
Web App as Application Server

Code On Time web applications have a classic multitier architecture.

  • A backend database engine (Oracle, SQL Server, MySQL, etc.) provides the data tier.
  • The application tier is a generated application. It includes a standard framework with custom business rules created by a developer. Application framework interacts with the data tier. It automatically creates data manipulation SQL statements and invokes business rules as defined by the app configuration.
  • The presentation tier is a standard library implemented in JavaScript. The library is stored with the application files on the web server. The client library is downloaded by a web browser with application pages. The client library components interact with the server-side application framework and business rules.

The client library of the presentation tier has a model-view-controller architecture. It retrieves the model and view configuration from the application tier and presents data in a web browser window. It also sends user-initiated actions to the application framework for execution.

A web app configuration information and data are traveling between application and presentation tiers over HTTP protocol through a single web service implemented in the application framework. The presence of configuration information allows the same client library to be used in many applications without the need for heavy customization of generated apps.

The standard client library can be enhanced with new capabilities and even replaced to support new types of client devices.

Here is an example of Customers data controller from the Northwind sample created with Code On Time.

The highlighted view createForm1 includes the fields from the model  The highlighted action ag3 / a1 requires command New to be executed with the argument createForm1

The highlighted view createForm1 includes the fields from the model.

The highlighted action ag3 / a1 specifies that New command must be executed with the argument createForm1.

These application configuration elements do not imply any specific implementation. A developer can put together a custom app based on such configuration. The client library of a Code On Time web application provides just one of the many possible implementations.

This is how the client library of a Code On Time web app interprets the application configuration of the 'Customers' data controller

Northwind database is the data management system of a mail order trading company. In minutes, a developer can generate a fully functional secure web app straight from the database. The app can be used for back office data management of orders and inventory by company employees.

Today, it is expected that the business data is available literally everywhere – any device and any platform must be supported.

Suppose that the public-facing web site of Northwind Traders must be enhanced to allow self-registration of customers. The web site is deployed to a Linux web server.

This is how the form may look.

This sample form can be used to register new customers in a web app created with Code On Time Unlimited edition

The registration form users are anonymous and have no access to the back office system. The operating system of the web app is Microsoft Windows. The app is deployed to a dedicated Windows Azure server, while the public web site is running on a Linux server hosted by a different provider.

A web app created with Code On Time offers an amazingly simple and powerful solution to this challenge.

Create a file with “.htm” extension with the following HTML markup.

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Customer Registration Form</title>
</head>
<body>
    <form action="http://demo.codeontime.com/northwind/appservices/Customers" method="post">
    <table>
        <tr>
            <td>
                Customer ID
            </td>
            <td>
                <input type="text" name="CustomerID" size="5" />
            </td>
        </tr>
        <tr>
            <td>
                Company Name
            </td>
            <td>
                <input type="text" name="CompanyName" size="40" />
            </td>
        </tr>
        <tr>
            <td>
                Phone
            </td>
            <td>
                <input type="text" name="Phone" size="24" />
            </td>
        </tr>
    </table>
    <input type="submit" value="Register" />
    <!-- redirection parameters  -->
    <input type="hidden" name="_successUrl" value="http://codeontime.com/buy" />
    <input type="hidden" name="_errorUrl" value="http://codeontime.com/support" />
    </form>
</body>
</html>

Open the file in your favorite web browser, fill the form, and hit “Register” button. If the primary key of the new customer is unique, then a new customer record will be automatically created in the database of http://demo.codeontime.com/northwind web app and you will be redirected to the URL specified in _successUrl parameter. Otherwise the browser will be redirected to the URL specified in _errorUrl parameter. The _error variable added to the URL will indicate the source of the problem.

Sign in the application to locate the new registration record at http://demo.codeontime.com/Northwind/Pages/Customers.aspx. Enter admin/admin123% credentials to access the page if prompted.

The data records of a self-registered customer created as a result of standard HTML form submission

The demo application at http://demo.codeontime.com/northwind “listens” to HTTP requests that start with “/appservices” prefix.

If you click on the link http://demo.codeontime.com/northwind/appservices/Customers specified in the “action” attribute of the form, then an XML list of customers will be returned. The web browser will use HTTP GET method when requesting the URL.

The form declares that HTTP POST method shall be used when the form is submitted. The demo app will interpret the request as a command to insert a data row. The application data controller will automatically use createForm1 to perform the action. If there are any custom business rules defined in the app, then they will be automatically engaged as well and may effect the result of the action.

The application framework of a Code On Time web app provides a full fledged custom application server. Developer creates application server APIs  by customizing views, actions, and business rules in the application data controllers. From the developer’s prospective, the customization of these project configuration elements results in a made-to-measure user interface. All of a sudden this work goes a long way towards creating a highly reusable application server.

The user interface of a Code On Time web app can be used on its own or function as a test platform for the application server APIs of the next killer app created for any platform supporting HTTP, JSON, and XML.

The application framework includes components that implement support for Representational State Transfer also known as REST.  The application can handle HTTP requests to the  built-in custom application server with responses encoded in JSON or XML when enabled.