Application Builder

Labels
AJAX(112) App Studio(9) 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(178) 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(184) 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(3) 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
Application Builder
Saturday, August 16, 2014PrintSubscribe
Reports at Attachments in Email Business Rules

Application framework allows generating reports on the server. This capability makes it possible to produce reports as attachments of email business rules.

Consider the following Email Business Rules implementing a simple notification executed in response to Update command in Categories data controller.

Property Value
Command Name Update
Type Email
Phase After
Script
Host: smtp.gmail.com
Port: 587
UserName: YOUR_EMAIL_ADDRESS@gmail.com
Password: PASSWORD
EnableSSL: true

From: "Sales Admin" <YOUR_EMAIL_ADDRESS@gmail.com>
To: RECIPIENT@northwind.com
Subject: Category "{CategoryName}" has changed!

Dear Admin,

This product category has been changed.
See attachment for category product details.

System Monitor

<attachment type="report">
    <name>{CategoryName}</name>
    <controller>Categories</controller>
    <view>editForm1</view>
    <filter>
        <item>
            <field>CategoryID</field>
            <operator>=</operator>
            <value>{CategoryID}</value>
        </item>
    </filter>
</attachment>
<attachment type="report">
    <name>{CategoryName} Products</name>
    <controller>Products</controller>
    <sortExpression>UnitPrice desc</sortExpression>
    <filter>
        <item>
            <field>CategoryID</field>
            <operator>=</operator>
            <value type="Int32">{CategoryID}</value>
        </item>
    </filter>
</attachment>

Note the two attachment elements embedded directly in the email message. Each element defines a snippet of XML markup describing the report execution arguments.

The first attachment is produced for Categories data controller. Data is filtered by CategoryID of the modified record. The report is produced for editForm1 view.

The second attachment is produced for Products data controller. Data is filtered by CategoryID and sorted in descending order of Unit Price. The report is produced for grid1 view.

Note the field names of the updated data record referenced in curly braces. Expressions {CategoryName} and {CategoryID} are replaced with the actual values during processing.

Attachment definitions are removed from the email body by application framework. The framework will generate each report using specified arguments and attach the report to the email before it is sent out to the recipient.

Run the application and edit any category. Click OK button to save the changes.

An email business rule will trigger an email notification with two report attachments produced in a Touch UI app created with Code On Time application generator.

The data will be saved after a slight delay.

Check your smart phone device for messages.

An email notification on an Android device generated by an Email Business Rule of an app produced with Code On Time.

This is how the email message may look.

The text of the email notification produced by an Email Business Rule in an app created with Code On Time applicaition generator.

Click on an attachment to see the report data in a PDF reader installed on your device.

An attachment report with Category details displayed in Adobe Reader on an Android device.

An attachment report with a list of Products in changed category displayed in Adobe Reader on an Android device.

Saturday, August 16, 2014PrintSubscribe
Producing Reports in Binary Format

Application end users download the data reports by selecting menu options in the user interface.

Standard reporting options in an app with Touch UI produced with Code On Time application generator.

The report is produced in the requested format on the server and streamed back to the client browser. The report data is automatically filtered and sorted exactly as displayed to the end user.

A report produced in Microsoft Word format by an app with Touch UI created with Code On Time application generator.

Application developers may need to produce a report on the server with arbitrary filters and sort expression in response to the user actions. The report data file may be stored in the database, archived in the file system, or sent as an email attachment. Application framework offers a simple method that allows to do just that.

Consider the following sample business rule.

C#:

using System;
using System.Data;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.Security;
using MyCompany.Data;
using MyCompany.Handlers;
using System.IO;
using MyCompany.Web;

namespace MyCompany.Rules
{
    public partial class CustomersBusinessRules : 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 "ProduceReport".
        /// </summary>
        [Rule("r100")]
        public void r100Implementation(string customerID, string companyName, string contactName,
            string contactTitle, string address, string city, string region, string postalCode,
            string country, string phone, string fax)
        {
            // This is the placeholder for method implementation.
            ReportArgs args = new ReportArgs();
            // controller
            args.Controller = "Orders";
            // sort expression
            args.SortExpression = "OrderDate desc";
            // data filter
            args.Filter = new FieldFilter[] {
                new FieldFilter  {
                    FieldName = "CustomerID",
                    Operation = RowFilterOperation.Equal,
                    Value = customerID
                }
            };
            // filter details
            args.FilterDetails = "This report has been produced on the server for customer " + companyName;
            // produce report in binary format
            byte[] reportData = Report.Execute(args);
            // save report to the local file system
            File.WriteAllBytes(Path.Combine(
                Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "Test.pdf"),
                reportData);
            // report the MIME type and file extension that go with the binary data
            Result.ShowAlert("MIME: {0}, Extension: {1}", args.MimeType, args.FileNameExtension);
        }
    }
}

Visual Basic:

Imports MyCompany.Data
Imports System
Imports System.Collections.Generic
Imports System.Data
Imports System.Linq
Imports System.Text.RegularExpressions
Imports System.Web
Imports System.Web.Security
Imports MyCompany.Handlers
Imports System.IO
Imports MyCompany.Web

Namespace MyCompany.Rules

    Partial Public Class CustomersBusinessRules
        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 "ProduceReport".
        ''' </summary>
        <Rule("r100")> _
        Public Sub r100Implementation(ByVal customerID As String, ByVal companyName As String,
                                      ByVal contactName As String, ByVal contactTitle As String,
                                      ByVal address As String, ByVal city As String,
                                      ByVal region As String, ByVal postalCode As String,
                                      ByVal country As String, ByVal phone As String, ByVal fax As String)
            'This is the placeholder for method implementation.
            Dim args As ReportArgs = New ReportArgs()
            ' controller
            args.Controller = "Orders"
            ' sort expression
            args.SortExpression = "OrderDate desc"
            ' data filter
            args.Filter = New FieldFilter() {
                New FieldFilter With {
                    .FieldName = "CustomerID",
                    .Operation = RowFilterOperation.Equals,
                    .Value = customerID
                    }
                }
            ' filter details
            args.FilterDetails = "This report has been produced on the server for customer " + companyName
            ' produce report in binary format
            Dim reportData As Byte() = Report.Execute(args)
            ' save report to the local file system
            File.WriteAllBytes(Path.Combine(
                Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "Test.pdf"),
                reportData)
            ' report the MIME type and file extension that go with the binary data
            Result.ShowAlert("MIME: {0}, Extension: {1}", args.MimeType, args.FileNameExtension)
        End Sub
    End Class
End Namespace

The code is executed in response to a custom action Produce Report selected in the context menu of application.

Custom action used to invoke a 'Code' business rule in an app with Touch UI creatd with Code On Time application builder.

Static method Report.Execute performs a server-side execution of the standard report action. The custom implementation of the “Code” business rule displays details about the produced binary data array.

Information about MIME type and file extension reporting by a business rule after producing a report in PDF format in an app with Touch UI.

This sample saves the report data to My Documents folder of the server computer. Here is the actual report.

This report has been generated by a custom action with the help of Report.Execute method invoked by custom business rule in an app with Touch UI produced with Code On Time.

Instance of a class ReportArgs exposes several properties that control the report rendering on the server.

Property Description
Controller Specifies the name of the data controller.
View Specifies the ID of the data controller view that will be used to produce data.
SortExpression Defines a sort expression that determines the order of data rows passed to the reporting engine for processing.
Filter Defines an array of filters applied to the report data passed to the reporting engine for processing.
FilterDetails Specifies the optional message displayed below the report header in standard reports.
Format Specifies the format of the output. The default format is Pdf. Other options are Word, Excel, and Image.
Template Name Specifies the name of the custom report template. If left blank, then a standard template is automatically created by application framework.
MimeType Indicates the MIME type of the report data produced by Microsoft Report Viewer. Use this property when sending report as an email attachment.
FileNameExtension Indicates the file name extension that matches the data produced by Microsoft Report Viewer. Use this property to provide a correct extension for the file name.
Saturday, August 9, 2014PrintSubscribe
Passing Business Rule Properties to Stored Procedures

Code On Time generator allows creating data controllers from the result set of a stored procedure. Some stored procedures use parameters in order to perform operations on the data. In the Northwind sample database, the [Employee Sales By Country] stored procedure shows total sales amounts grouped by employee, and then by country. It accepts two parameters, @Starting_Date and @Ending_Date to determine the filter.

Let’s create a controller from this stored procedure and pass parameters to the script via properties in the BusinessRules class of the app.

This picture shows the results of the stored procedure with @Beginning_Date and @Ending_Date parameters returned by a business rule property.

Employee Sales by Country stored procedure results filtered by a business rule property.

The CREATE script for the stored procedure can be seen below.

CREATE procedure [dbo].[Employee Sales by Country] 
@Beginning_Date DateTime, @Ending_Date DateTime AS
SELECT    Employees.Country, 
        Employees.LastName, 
        Employees.FirstName, 
        Orders.ShippedDate, 
        Orders.OrderID, 
        "Order Subtotals".Subtotal AS SaleAmount
FROM Employees INNER JOIN 
    (Orders INNER JOIN "Order Subtotals" ON Orders.OrderID = "Order Subtotals".OrderID) 
    ON Employees.EmployeeID = Orders.EmployeeID
WHERE Orders.ShippedDate Between @Beginning_Date And @Ending_Date

Creating the Controller

Start the Project Designer. In the Project Explorer, switch to the Controllers tab. Click on the New Controller icon on the toolbar.

Creating a new controller.

Enter a name for the controller.

Property Value
Name EmployeeSalesByCountry

Press OK to save. Right-click the new controller and press “Generate From SQL…”.

Generating the controller from an SQL script.

In the SQL script textbox, paste in the following script. The debug section is removed from the business rule when the application framework executes the script at runtime and declares the business rule properties as SQL parameters.

-- debug
DECLARE @BusinessRules_BeginningDate datetime,
        @BusinessRules_EndingDate datetime
-- end debug

EXEC [dbo].[Employee Sales by Country]
    @BusinessRules_BeginningDate,
    @BusinessRules_EndingDate

Press OK to generate the controller.

Adding Controller To Page

Next, let’s add the controller to a page. Right-click on the controller and press Copy.

Copying the EmployeeSalesByCountry controller.

Switch to the Pages tab in the Project Explorer. On the toolbar, press the New Page icon.

Creating a new page in the project.

Give a name to the page and press OK to save.

Property Value
Name Employee Sales By Country

Drop the new page to the right side of Home page node to place it second in the site menu.

Dropping a page to the right side of Home page node.     Employee Sales By Country page placed after the Home page node in the site menu.

Right-click on the page and press Paste to instantiate the controller as a data view on the page.

Pasting on the Employee Sales By Country page.     The EmployeeSalesByCountry controller has been added to the page as a data view.

Adding Business Rule Property

Let’s create two properties in the BusinessRules class. These properties will return a DateTime value that will be picked up and used by the query to filter the results. If the user is in role “Administrators”, it will display all records between 1970 and 2000. Otherwise, no records will be displayed.

On the Project Designer toolbar, press Browse to first generate the web app. Then, press Develop to open the solution in Visual Studio.

In the Solution Explorer on the right side, right-click on App_Code folder and press Add | Class.

Adding a new class to the project.

Assign a name of “EmployeeSalesByCountryProperties” and press OK to create the file. Replace the contents of the file with the following:

C#:

using System;

namespace MyCompany.Data
{
    public partial class BusinessRules
    {
        public static DateTime BeginningDate
        {
            get
            {
                if (Controller.UserIsInRole("Administrators"))
                    return new DateTime(1970, 1, 1);
                else 
                    return DateTime.Now;
            }
        }

        public static DateTime EndingDate
        {
            get
            {
                if (Controller.UserIsInRole("Administrators"))
                    return new DateTime(2000, 1, 1);
                else
                    return DateTime.Now;
            }
        }
    }
}

Visual Basic:

Imports Microsoft.VisualBasic

Namespace MyCompany.Data
    Partial Public Class BusinessRules

        Public ReadOnly Property BeginningDate As DateTime
            Get
                If Controller.UserIsInRole("Administrators") Then
                    Return New DateTime(1970, 1, 1)
                Else
                    Return DateTime.Now
                End If
            End Get
        End Property

        Public ReadOnly Property EndingDate As DateTime
            Get
                If Controller.UserIsInRole("Administrators") Then
                    Return New DateTime(2000, 1, 1)
                Else
                    Return DateTime.Now
                End If
            End Get
        End Property

    End Class
End Namespace

Make sure to save the file.

Viewing the Results

Press Ctrl+F5 to start the app without debugging. Log in as an administrator and navigate to the Employee Sales By Country page. Notice that all 809 records are displayed.

All employee sales are displayed.

Log out, and log in again as a user. Notice that no records are displayed.

No employee sales are displayed.