Touch UI

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
Touch UI
Monday, August 18, 2014PrintSubscribe
Reports as Email Attachments, Data Views without Extenders, Azure SDK 2.4

Code On Time release 8.0.8.0 introduces the following features and fixes.

  • Implemented support for attachments in Email Business Rules. Multiple xml tags <attachment/> can be specified in the body of the email template.
     
  • Added SMTP settings to Features page of Project Wizard
     
  • Report handler now supports static method Report.Execute to enable generation of report data on the server. The method accepts filter, sort expression, controller, view, template name, and output format as parameters.
     
  • SQL business rules can generate emails. This allows creating multiple complex emails with optional attachments using the full power of SQL dialect of the database engine.
    1) First, a business rule must set EnableEmailMessages property of the business rules class.
    2) Next, another business rule executing in the same sequence will return a list of data rows with columns titled as "To", "Subject", "Body", etc. to produce a list of outgoing emails.
     
  • Desktop and Touch UI now support parsing of "data-" attributes to enable initialization of data views from user controls without using server-side tags. This feature will be the core capability in http://cloudontime.com virtual pages. We are also considering replacing DataViewExtender references with the new “data-” attributes in the generated pages. For example, a master detail relationship between Categories and Products can be declared with this snippet of XML:
    <div id="categories" data-controller="Categories" data-show-in-summary="true"></div>
    <div id="products" data-controller="Products" 
        data-filter-fields="CategoryID" data-filter-source="categories"></div>
    
       
  • Generate from SQL will include byte fields if "base Table Name" is specified. Base table name will be used to create the controller to ensure the labels make sense.
     
  • Updated "Generate From SQL..." function to add up to 1000 data fields to grid1.
     
  • Added ability to "not create controllers automatically" when creating a new project. This will create a database object filter of "__none" and will not create any controllers.
     
  • If multiple views are available, then page header is not displayed in grid/list below the tabs representing view names in Touch UI apps.
     
  • Touch UI recognizes data-content-framework attribute on custom pages to enable upcoming support for built-in CMS (content management system). The future supported values are "bootstrap" and "" (empty string).
     
  • Custom pages do not fire appscroll events to improve performance of long “bootstrap” pages.
     
  • Wide and Tall pages will disabled sidebar and page header in Touch UI applications.
     
  • First virtual page of the data app will not display  a page header
     
  • Custom controls can use data-page-header attribute to set up the text of the page header in Touch UI apps. The page header is inherited from activator label (if any) and will not be displayed if it matches the first page.
     
  • Azure SDK 2.4 is now supported in Azure Factory project type.
     
  • Implemented enhanced processing of Azure SDK references to prevent duplicates created after Azure SDK upgrade. Azure Factory project do not include a reference to Azure Storage for Azure SDK 2.4. It must be added manually when needed.
     
  • Negative search with quick find now requires a space in front of the sample. So the search sample "to-do" will not be treated as "positive 'to' and negative 'do'".
     
  • Moved resetting of Result.Canceled to beginning of SelectedValue loop to allow PreventDefault on each individual selected row in business rules executed for data view with multiple row selection.
     
  • Report handler uses a more robust method of figuring the base URL of application to ensure correct image URLs in reports.
     
  • Application framework adds "order by row_number__" to "SELECT" requests to ensure consistent results on multi-processor machines running SQL Server. Thank you Patrick Saunders and fgary6861!
     
  • The contents of "virtual" pages marked as data-app-role="page" is wrapped in a div with class app-page-content. This significantly improves the rendering of Bootstrap content pages in CMS.
     
  • Touch UI: Settings menu displays "Settings" label.
     
  • Touch UI: Action Group menus of actions display header text of action group as a header for the panel.
     
  • Touch UI: Method $app.mobile.navigate navigates to a virtual page. The method must be used when programming custom virtual pages to complete navigation.
     
  • Touch UI: The framework will not auto-enhance virtual pages marked as data-enhance="false".
     
  • Touch UI: Custom user controls can implement "delayed" transitions to pages if remote data is required to display the page. The tutorials are coming up this week.
     
  • Touch UI: Action groups with child items are displayed on the sidebar.
     
  • Property "field" can be used to reference field names when configuring filters for Web.DataView.search and $app.execute methods.
     
  • Method $app.execute will execute "Select" command if a command is not specified. It will also use "grid1" as the default view Id.
     
  • Data controllers based on Result Sets produced by business rules will work correctly with field names that contain non-alphanumeric characters or starting with numbers.
     
  • Touch UI: User controls without activators do not have an empty link on the "main" user interface page.
     
  • Added null field check for negative quick find searches.
     
  • Generate button in Project Designer will always be shown if "Browse" is hidden.
     
  • Fixed DotNetNuke project file to create Web.*.config files in /WebApp, not /Sandbox folder.
     
  • Project Designer's "Generate" button will be hidden if User Interface = Touch UI.
     
  • Touch UI: View selector options in context menu will synchronize with the view selection tabs of grid/list.
     
  • Modified "Data Controller" construction selectors on "Database Connection" page.
     
  • Fix the bug causing Quick Find to fail if "," without a following query sample are entered.
     
  • Select "includes" / "does not include" filter in advanced search bar if another search criteria is present will not throw an exception in Desktop UI.
     
  • Fixed the spelling with incorrect processing of map-latitude and map-longitude tags in Touch UI apps.
     
  • Included new translated resources in hr locale. Thank you uremovic!
     
  • Updated lookups to use sort expression of view.
     
  • Moved execution of ControllerAction methods into "InternalExecuteBusinessRules" method to ensure parity between those methods and business rules.
     
  • Minimized simultaneous appearance of multiple progress indicators in Touch UI apps.
     
  • Enhanced visual appearance of Dedicated Login in Touch UI.
     
  • Touch UI:  Summary views are refreshed only if they are visible on the page and are in the direct sight of a user.
     
  • Negative search uses NULL value check on fields to ensure correct output. Previously presence of NULL values in a data row was causing exclusion of correct “negative” data rows from the output.
Saturday, August 9, 2014PrintSubscribe
Passing Parameter to Stored Procedure using a Custom Search Dialog

Code On Time apps offer the ability to display the results of a stored procedure. Some stored procedures require passing an SQL parameter in order to perform manipulations 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. By default, the stored procedure will display all records between the years 1970 and 2000. In addition, we will add a custom action that will allow the user to specify the Beginning and Ending dates via a custom confirmation controller.

The picture below shows the confirmation controller form allowing the user to specify parameters for the stored procedure.

The confirmation controller form allows the user to select a beginning and ending date to pass to the stored procedure.

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 to Display the Stored Procedure

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 SQL.

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 parameters.

-- debug
DECLARE @Session_BeginningDate datetime, @Session_EndingDate datetime
-- end debug

if (@Session_BeginningDate is null)
    set @Session_BeginningDate = '1970'

if (@Session_EndingDate is null)
    set @Session_EndingDate = '2000'


EXEC [dbo].[Employee Sales by Country]
    @Session_BeginningDate,
    @Session_EndingDate

Press OK to generate the controller.

Setting the Session Variable

Note that the parameters returned from the search dialog will not be cached. These parameters must be saved into a session variable. In the Project Explorer, double-click on the EmployeeSalesByCountry / Business Rules / Select (Sql / Before) – enableResultSet node.

Selecting the 'enableResultSet' business rule from the EmployeeSalesByCountry controller.

Replace the script with the following:

set @BusinessRules_EnableResultSet = 1
-- Enable caching of the result set. Duration is specified in seconds.
-- set @BusinessRules_ResultSetCacheDuration = 30 

if (@Parameters_BeginningDate is not null)
    set @Session_BeginningDate = @Parameters_BeginningDate

if (@Parameters_EndingDate is not null)
    set @Session_EndingDate = @Parameters_EndingDate

Press OK to save the new script.

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.

Adding a page to the app.

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 of the Home page node.     Employee sales by country page is now second in the site menu.

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

Pasting onto the 'Employee Sales By Country' page.     The EmployeeSalesByCountry controller has been instantiated as a view on the page.

Adding the Custom Action

Switch back to the Controllers tab in the Project Explorer. Right-click on EmployeeSalesByCountry / Actions / ag3 (ActionBar) – New node, and press New Action.

Creating a new action in the 'EmployeeSalesByCountry' controller.

Specify the following values:

Property Value
Command Name Search
Header Text Filter View
Confirmation

_controller=FilterEmployeeSales
_title=Select the Beginning and Ending Dates

Press OK to save the action.

Creating the Confirmation Controller

Let’s add a controller that will allow the user to specify BeginningDate and EndingDate parameters for the stored procedure.

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

Adding a new controller to the project.

Enter a name for the controller.

Property Value
Name

FilterEmployeeSales

Click OK to save the controller. Right-click on FilterEmployeeSales / Fields node, and press New Field.

Adding a new field to the 'FilterEmployeeSales' controller.

Define the field as follows:

Property Value
Name BeginningDate
Type DateTime

Save the field, and create a second field with these values:

Property Value
Name EndingDate
Type DateTime

Save the EndingDate field. The confirmation controller is now complete.

Viewing the Results

On the Project Designer toolbar, press Browse. In the browser window that will open, navigate to the Employee Sales By Country page. Note that all 809 records are displayed.

All 809 records are displayed on the 'Employee Sales By Country' page.

In the sidebar or context menu, press Filter View action. The page will navigate to a form with the Beginning Date and Ending Date fields. Enter values, and press OK.

The confirmation controller form allows the user to select a beginning and ending date to pass to the stored procedure.

Note that the parameters have been passed to the stored procedure and there are only 17 records displayed now.

The BeginningDate and EndingDate parameters have been set by the confirmation controller.

Thursday, July 31, 2014PrintSubscribe
Creating Data Controller From Web Service

Code On Time web app generator automatically creates controllers for any specified tables and views from your database. In addition, you can define new controllers from any SQL query. One can also choose to display data from any data source using C# or Visual Basic business rules – you are only limited by your imagination.

In this example, let’s request a list of articles recently published on /blog. A sample application showing the blog posts can be seen below.

The list of posts retrieved from the web service is displayed in a list.

The URL that will be used to compose a REST request is the following:

http://www.blogger.com/feeds/2297698770491701674/posts/default/

You can see an example of the response with the essential items highlighted below.

<?xml version='1.0' encoding='UTF-8'?>
<?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?>
<feed xmlns='http://www.w3.org/2005/Atom' ...>
  ...
  <entry>
    ...
    <published>2014-07-13T22:25:00.000-07:00</published>
    <updated>2014-07-15T00:03:46.566-07:00</updated>
    ...
    <title type='text'>
      Map View, Master-Detail Pages, 
      Custom Result Sets, Client-Side APIs
    </title>
    <content type='html'>
      &lt;p&gt;&lt;a title="Code On Time generator creates line-of-business Web Apps ...
    </content>
    ...
  </entry>
  <entry>
    ...
    <published>2014-07-13T10:00:00.000-07:00</published>
    <updated>2014-07-13T17:11:25.294-07:00</updated>
    ...
    <title type='text'>Assigning a Theme to a Page</title>
    <content type='html'>
      &lt;p&gt;&lt;a title="Code On Time Generator is a premier web application ...
    </content>
    ...
  </entry>
  ...
</feed>

The code business rule will need to accept this XML, create a data table and convert each “entry” element into a data row. The data rows will have four columns – Published, Updated, Title, and Content.

Defining the Controller

The first step is to define a controller that will handle the data table. One possible way of defining the controller would be to simply create it in the Project Designer. However, let’s take advantage of the automatic field, view, data field, and action generation provided by the Define Data Controller tool.

Start the Project Designer. In the Project Explorer, switch to the Controllers tab and press the New Controller icon.

Creating a new controller in the Project Explorer.

Give the controller a name:

Property Value
Name Posts

Press OK to save the new controller. Expand the new controller in the Project Explorer, and right-click on the Fields node. Select New Field option.

Creating a new field in the Posts controller.

Define the following properties:

Property Value
Name Title
Type String
Length 256

Press OK to save. Create another field with these properties:

Property Value
Name Content
Type String
Html Encoding False

Save the field, and add another:

Property Value
Name Published
Type DateTime

Save, and add the Updated field:

Property Value
Name Updated
Type DateTime

Save the last field. Right-click on the controller, and press Generate From Fields.

Generating the controller from the field definitions.

This will proceed to generate views, data fields, actions, and several code business rules to override CRUD operations. No command will be created.

The controller has been generated from the fields.

The first code business rule will provide an outline for defining the result set. The next three rules simply override the Insert, Update, and Delete actions and call PreventDefault() method. The developer must implement these rules in order for the respective actions to work.

On the toolbar, press Browse to regenerate the app and create the code files. When complete, right-click on Posts / Business Rules / Select (Code / Before) – GetData business rule, and press Edit Rule In Visual Studio.

Editing the rule in visual studio.

The file will open in Visual Studio. The business rule will create a DataTable object by calling to CreatePostsDataTable() method. The default implementation of this method will simply return a data table with no data.

[Rule("GetData")]
public void GetDataImplementation(
    string title, 
    string content, 
    DateTime? published, 
    DateTime? updated)
{
    ResultSet = CreatePostsDataTable();
}
        
private DataTable CreatePostsDataTable()
{
    DataTable dt = new DataTable();
    dt.Columns.Add("Title", typeof(String));
    dt.Columns.Add("Content", typeof(String));
    dt.Columns.Add("Published", typeof(DateTime));
    dt.Columns.Add("Updated", typeof(DateTime));
    // 
    // Populate rows of table "dt" with data from any source 
    // (web service, file system, database, etc.)
    //
    return dt;
}

Let’s complete the implementation by providing the data for the data table. At the top of the file, add the following using/import directive:

C#:

using System.Xml;

Visual Basic:

Imports System.Xml

Then, replace the “Populate rows of table” comment after the data table is declared with the following code. The code will make a request to Blogger, read in each “entry” element and create a new data row in the table using the values of that element.

C#:

// get data into table
XmlReader reader = XmlReader.Create(
    "http://www.blogger.com/feeds/2297698770491701674/posts/default/");
reader.ReadToDescendant("entry");
while (reader.LocalName == "entry")
{
    DataRow r = dt.NewRow();
    XmlReader subtree = reader.ReadSubtree();

    if (subtree.ReadToDescendant("published"))
    {
        r["Published"] = subtree.ReadElementContentAsDateTime("published",
            "http://www.w3.org/2005/Atom");
        r["Updated"] = subtree.ReadElementContentAsDateTime("updated",
            "http://www.w3.org/2005/Atom");
        while (subtree.LocalName != "title")
            subtree.Read();
        r["Title"] = subtree.ReadElementContentAsString("title",
            "http://www.w3.org/2005/Atom");
        r["Content"] = subtree.ReadElementContentAsString("content",
            "http://www.w3.org/2005/Atom");

        dt.Rows.Add(r);
    }

    if (!reader.ReadToFollowing("entry") || reader.EOF)
        break;
}

Visual Basic:

Dim reader As XmlReader = XmlReader.Create(
                "http://www.blogger.com/feeds/2297698770491701674/posts/default/")
reader.ReadToDescendant("entry")
While reader.LocalName = "entry"
    Dim r As DataRow = dt.NewRow()
    Dim subtree As XmlReader = reader.ReadSubtree()

    If subtree.ReadToDescendant("published") Then
        r("Published") = subtree.ReadElementContentAsDateTime("published",
                                                              "http://www.w3.org/2005/Atom")
        r("Updated") = subtree.ReadElementContentAsDateTime("updated",
                                                            "http://www.w3.org/2005/Atom")
        While subtree.LocalName <> "title"
            subtree.Read()
        End While
        r("Title") = subtree.ReadElementContentAsString("title",
                                                        "http://www.w3.org/2005/Atom")
        r("Content") = subtree.ReadElementContentAsString("content",
                                                          "http://www.w3.org/2005/Atom")

        dt.Rows.Add(r)
    End If

    If Not reader.ReadToFollowing("entry") OrElse reader.EOF Then
        Exit While
    End If
End While

Make sure to save the file.

Adding the Page and Viewing the Results

Switch back to the Project Designer. Right-click on the Posts controller node, and press Copy.

Copying the 'Posts' controller.

Switch to the Pages tab in the Project Explorer. Click on the New Page icon.

Creating a new page from the Project Explorer.

Assign a name.

Property Value
Name Posts

Press OK to save the page. Drag the new page in the Project Explorer to the right of Home page node to place it second in the site menu.

Dropping the page on the left side of the Home page node.     The 'Posts' page has been placed second in the site menu.

Right-click on the new page and press Paste to bind the controller to the page.

Pasting onto the 'Posts' page.     The data controller has been bound with a data view.

On the toolbar, press Browse to generate and open the web app in the default browser. The list of posts retrieved from the web service is displayed on the page. Note that you must define a primary key before any of the items can be selected.