Business Rules/Logic

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
Business Rules/Logic
Friday, September 21, 2012PrintSubscribe
Windows Client of a Web App

A web app created with Code On Time may function as an application server for a client on any platform.

Let’s create a native Windows Forms application that will allow browsing and searching products available at http://demo.codeontime.com/Northwind/Pages/Products.aspx.

This is how a Quick Find search is performed by the web app. The native Windows client will provide a similar presentation and search facility.

The 'Quick Find' feature in action in a web app created with Code On Time

Click on the following link and you will see a response in XML format from the REST service of the web application:
http://demo.codeontime.com/northwind/appservices/Products?_q=40%20biscuit

The response will look similar to this sample.

<?xml version="1.0" encoding="utf-8"?>
<Products totalRowCount="2" pageSize="100" pageIndex="0" rowCount="2">
  <items>
    <item ProductName="Sir Rodney's Marmalade" SupplierID="8" CategoryID="3" 
          QuantityPerUnit="30 gift boxes" UnitPrice="$81.00" UnitsInStock="40" 
          UnitsOnOrder="0" ReorderLevel="0" Discontinued="False" ProductID="20" 
          SupplierCompanyName="Specialty Biscuits, Ltd." 
          CategoryCategoryName="Confections" />
    <item ProductName="Sir Rodney's Scones" SupplierID="8" CategoryID="3" 
          QuantityPerUnit="24 pkgs. x 4 pieces" UnitPrice="$10.00" UnitsInStock="3" 
          UnitsOnOrder="40" ReorderLevel="5" Discontinued="False" ProductID="21" 
          SupplierCompanyName="Specialty Biscuits, Ltd." 
          CategoryCategoryName="Confections" />
  </items>
</Products>

The “_q” parameter represents the Quick Find argument of the web resource. If the parameter is not specified, then the first 100 items are returned. Other parameters for sorting, paging, and filtering are also supported.

The native Windows client of the Northwind application server will construct a similar URL to retrieve data for presentation.

Start Visual Studio and select File | New Project option. Choose Windows Forms Application under Visual C# or Visual Basic template group, enter “ProductBrowser” in the name, and click OK to create project files.

The empty 'Northwind Product Browser' project contains a single Windows Form

Drop TextBox, Button, and ListView components from toolbox on the design surface of Form1 and have them arranged as shown next.

Form 'Form1' enhanced with a TextBox, Button, and ListView components

Use Properties Window to modify the Columns collection of listView1. Create five columns Product Name, Supplier Company Name, Category Name, Quantity per Unit, and Unit Price to capture a few properties of products.

Five columns in the list view 'listView1' represent properties of products stored in the Northwind database

Also set the following properties of listView1 component:

Property Value
FullRowSelect True
GridLines True
View Details
VirtualMode True

The list view is configured to behave as a virtual view.

If the property VirtualListSize is set to a value other than zero then the virtual list view will request items from the application as needed.

The list view will continuously request items representing a visible subset of data rows as a user scrolls the list.

Right-click Form1 node in the Solution Explorer and select View Code option in the context menu.

Add the highlighted namespaces to the top of code file:

C#:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Xml.XPath;
using System.IO;

namespace ProductBrowser
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
    }
}

Visual Basic:

Imports System.Net
Imports System.Xml.XPath
Imports System.IO

Public Class Form1

End Class

The namespaces will link required .NET library components used by Windows native client to communicate with the web app.

Add fields _dataPage, _query, _cache, and method GetDataPage to the definition of class Form1.

C#:

protected XPathNavigator _dataPage;
protected string _query;

private SortedDictionary<int, XPathNavigator> _cache = new SortedDictionary<int, XPathNavigator>();

protected XPathNavigator GetDataPage(int pageIndex)
{
    XPathNavigator result = null;
    if (!_cache.TryGetValue(pageIndex, out result))
    {
        Cursor = Cursors.WaitCursor;
        try
        {
            WebRequest request = WebRequest.Create(String.Format(
                "http://demo.codeontime.com/northwind" +
                "/appservices/Products?_pageIndex={0}&_pageSize=10&_q={1}",
                pageIndex, _query));
            request.Method = "GET";
            using (WebResponse response = request.GetResponse())
            {
                using (Stream stream = response.GetResponseStream())
                    result = new XPathDocument(stream)
                        .CreateNavigator().SelectSingleNode("/Products");
            }
            _cache.Add(pageIndex, result);
        }
        finally
        {
            Cursor = Cursors.Default;
        }
    }
    return result;
}

Visual Basic:

Protected _dataPage As XPathNavigator
Protected _query As String

Private _cache As SortedDictionary(Of Integer, XPathNavigator) =
    New SortedDictionary(Of Integer, XPathNavigator)

Protected Function GetDataPage(pageIndex As Integer) As XPathNavigator
    Dim result As XPathNavigator = Nothing
    If Not (_cache.TryGetValue(pageIndex, result)) Then
        Cursor = Cursors.WaitCursor
        Try
            Dim request As WebRequest = WebRequest.Create(String.Format(
                "http://demo.codeontime.com/northwind" +
                "/appservices/Products?_pageIndex={0}&_pageSize=10&_q={1}",
                pageIndex, _query))
            request.Method = "GET"
            Using response As WebResponse = request.GetResponse()
                Using stream As Stream = response.GetResponseStream()
                    result = New XPathDocument(stream).
                        CreateNavigator().SelectSingleNode("/Products")
                    _cache.Add(pageIndex, result)
                End Using
            End Using
        Finally
            Cursor = Cursors.Default
        End Try
    End If
    Return result
End Function

The implementation of method GetDataPage creates a web request and retrieves the page of data from the web app if the page has not been found in the dictionary of cached data pages. The method parses the XML response received from the web app and stores an instance of XPathNavigator class initialized with a page data in the _cache field. The web request URI incorporates the requested page index and search criteria in _pageIndex and _q parameters accordingly.

Select listView1 in form designer and activate Properties Window, choose Events button, and double click RetrieveVirtualItem event.

Creating 'RetrieveVirtualItem' event handler for listView1 list view

Enter the following definition of the method listView1_RetrieveVirtualItem as shown next.

C#:

private void listView1_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e)
{
    // analyze the current page item range
int pageIndex = Convert.ToInt32(_dataPage.GetAttribute("pageIndex", String.Empty)); int pageSize = Convert.ToInt32(_dataPage.GetAttribute("pageSize", String.Empty)); int rowCount = Convert.ToInt32(_dataPage.GetAttribute("rowCount", String.Empty)); int firstAvailableRowIndex = pageIndex * pageSize; int lastAvailableRowIndex = firstAvailableRowIndex + rowCount - 1; // if the current page does not contain the item then retrieve the page from the app if (!(firstAvailableRowIndex <= e.ItemIndex && e.ItemIndex <= lastAvailableRowIndex)) { pageIndex = e.ItemIndex / pageSize; firstAvailableRowIndex = pageIndex * pageSize; _dataPage = GetDataPage(pageIndex); } // create a virtual list item XPathNavigator dataRow = _dataPage.SelectSingleNode( String.Format("items/item[{0}]", e.ItemIndex - firstAvailableRowIndex + 1)); e.Item = new ListViewItem(dataRow.GetAttribute("ProductName", String.Empty)); e.Item.SubItems.Add(dataRow.GetAttribute("SupplierCompanyName", String.Empty)); e.Item.SubItems.Add(dataRow.GetAttribute("CategoryCategoryName", String.Empty)); e.Item.SubItems.Add(dataRow.GetAttribute("QuantityPerUnit", String.Empty)); e.Item.SubItems.Add(dataRow.GetAttribute("UnitPrice", String.Empty)); }

Visual Basic:

Private Sub listView1_RetrieveVirtualItem(sender As System.Object,
        e As System.Windows.Forms.RetrieveVirtualItemEventArgs) Handles listView1.RetrieveVirtualItem
    ' analyze the current page item range
    Dim pageIndex As Integer = Convert.ToInt32(_dataPage.GetAttribute("pageIndex", String.Empty))
    Dim pageSize As Integer = Convert.ToInt32(_dataPage.GetAttribute("pageSize", String.Empty))
    Dim rowCount As Integer = Convert.ToInt32(_dataPage.GetAttribute("rowCount", String.Empty))
    Dim firstAvailableRowIndex As Integer = pageIndex * pageSize
    Dim lastAvailableRowIndex As Integer = firstAvailableRowIndex + rowCount - 1
    ' if the current page does not contain the item then retrieve the page from the app
    If Not (firstAvailableRowIndex <= e.ItemIndex And e.ItemIndex <= lastAvailableRowIndex) Then
        pageIndex = e.ItemIndex \ pageSize
        firstAvailableRowIndex = pageIndex * pageSize
       _dataPage = GetDataPage(pageIndex)
    End If
    ' create a virtual list item
    Dim dataRow As XPathNavigator = _dataPage.SelectSingleNode(
        String.Format("items/item[{0}]", e.ItemIndex - firstAvailableRowIndex + 1))
    e.Item = New ListViewItem(dataRow.GetAttribute("ProductName", String.Empty))
    e.Item.SubItems.Add(dataRow.GetAttribute("SupplierCompanyName", String.Empty))
    e.Item.SubItems.Add(dataRow.GetAttribute("CategoryCategoryName", String.Empty))
    e.Item.SubItems.Add(dataRow.GetAttribute("QuantityPerUnit", String.Empty))
    e.Item.SubItems.Add(dataRow.GetAttribute("UnitPrice", String.Empty))
End Sub

Consult the sample of XML response at the top of article to understand the method implementation.

The implementation makes an assumption that a page of XML data is stored in the _dataPage instance of XPathNavigator. The property e.ItemIndex specifies the index of the item that the virtual list view needs. The code tries to determine if the current data page contains the item. If the item is not in current page _dataPage, then the application will retrieve a page of data from the web app by invoking GetDataPage method. The method will either find the page in the cache or reach out to the web app with a web request for data.

Next, the event handler will create an instance of a ListViewItem. Its sub-items represent the values displayed in the columns of the list view. The instance of the ListViewItem is assigned to e.Item property.

At this point the entire mechanism of populating the list view with data has been implemented.

The only remaining step is to collect user input for the search criteria and to assign a value to the VirtualListSize property of listView1.

Activate the design surface of Form1 and double-click the Find button. This will create an event handler that shall be defines as explained below.

C#:

private void button1_Click(object sender, EventArgs e)
{
    // assign the search criteria
    _query = textBox1.Text;
    // remove any previously cached data pages
    _cache.Clear();
    // get the first page of data with index "zero"
    _dataPage = GetDataPage(0);
    // figure the total number of rows in the virtual listview
    int totalRowCount = Convert.ToInt32(_dataPage.GetAttribute("totalRowCount", String.Empty));
    listView1.VirtualListSize = totalRowCount;
}

Visual Basic:

Private Sub button1_Click(sender As System.Object, e As System.EventArgs) Handles button1.Click
    ' assign the search criteria
    _query = textBox1.Text
    ' remove any previously cached data pages
    _cache.Clear()
    ' get the first page of data with index "zero"
    _dataPage = GetDataPage(0)
    ' figure the total number of rows in the virtual listview
    Dim totalRowCount As Integer = Convert.ToInt32(_dataPage.GetAttribute("totalRowCount", String.Empty))
    listView1.VirtualListSize = totalRowCount
End Sub

The implementation of button1_Click method copies the search criteria from the text box in the field _query.  Then it clears the previously cached data pages and obtains the first page of data. Last, the method will figure the size of the virtual list.

In less than a hundred lines of code a remarkable functionality has been brought to life.

Press F5 to start the Northwind Product Browser for Windows. Click the Find button.

Product Browser retreives pages of data from the web app as user scrolls the list view

Try scrolling the list of products. The Windows client will make at the most 8 requests to retrieve the 77 products from the Northwind database sample. The page size in this implementation is deliberately set to 10 items to ensure that a client-server interaction does occur upon scrolling.  If the page size is not specified then the default page size of 100 will be used.

Enter “40 biscuit” in the text box textBox1 and hit the button one more time. The two products matching the search criteria will be retrieved. Compare the result to the web app screenshot at the top.

Product Browser perform 'Quick Find' function with the help of the application server emdeded in the web app created with Code On Time

The same technique of data paging can be used in any application that supports XML or JSON data formats. That includes Java applications and mobile native Android and iPhone/iPad apps.

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.