Blog: Posts from June, 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 June, 2012
Friday, June 15, 2012PrintSubscribe
Working with Pages

The Pages tab on the Project Explorer displays a hierarchy of application elements, starting with pages. Pages are composed of containers with data views and custom user controls.

Top-level pages are pages on the first level of the hierarchy.

The examples of top-level pages are Home, Customers, Employees, Categories, Customer Demographics, and Region. The examples of child pages are Orders, Customer Demo, Order Details, Employee Territories, and Products.

The Project Explorer displays a hierarchy of pages and page elements.

Creating a Page

A top-level page is created by clicking on the New Page icon on the toolbar.

New Page icon at the top of Project Explorer window.

This will open the New Page form where page properties can be specified.

The properties Name, Index, and Path effect the creation of a page.

The Name must be a unique sequence of alphanumeric characters that start with a letter.

The Index is an optional numerical order of the page. If it is not specified, then it will be assigned automatically when the page is saved. If it is specified, then the designer will try to position the page in the requested order.

The Path determines the hierarchical location of a page, as well as reflecting the text displayed on the menu to the end user. The vertical bar character “|” is used to separate multiple levels in the hierarchy. If there is no separator, then the page will be placed at the top of the hierarchy.

Below are sample settings for a new top-level page with a specific Index and Path.

Property Value
Name MyNewPage
Index 1005
Path My New Page

The page will be placed in the specified location based on the path and index when created in the Northwind sample.

New Page with index and path placed at specified location.

Here are the properties for a new page with an existing multi-level path.

Property Value
Name MyNewPage
Path Customers | Orders | My New Page

The page will be placed in the correct location. If the Path includes separators, then any Index is ignored, and the page is placed as the last child of an existing parent.

Page created with an existing mult-level path will be placed in the correct location.

If there is no matching path, then the missing parent pages will be created.

Property Value
Name MyNewPage
Path Customer2 | Orders | My New Page

The parent pages will have a special icon, because the External URL property of the parent pages is set to “about:blank”. Such pages will not have a physical implementation in the application and will simply designate static nodes in the navigation hierarchy.

Page created with a nonexisting multilevel path will create blank pages to match the path.

If a top-level page is created without a specified Index, then the page will be placed at the bottom of the hierarchy.

Property Value
Name MyNewPage
Path My New Page

The framework will automatically handle index allocation after the page is created – it will assign the first page with Index of “1000” and auto-increment by “10” for every succeeding page.

New Page with path but without index placed at the end of the list of pages.

If a page is created without a path, then it will become a system page. This page will not appear on the menu, but can be accessed via URL. The new system page will be added at the bottom of the hierarchy with a different icon. System pages are typically used to provide utility functions in applications and are meant to be presented to users through programmatic commands.

Page created without a path will be a system page.

When a page is selected in the Project Explorer, the New Child Page option will be available on the toolbar. It can also be accessed via the context menu of the page node.

New Child Page icon on the toolbar of Project Explorer.

Selecting this option will open the New Child Page form in the Designer window with Index and Path properties unavailable.

Specifying a name and creating a child page will add the page as the last child of the parent.

Creating a child page under Customers page node.

Rearranging Pages

Moving pages in the hierarchy can be accomplished by dragging and dropping the page nodes in the Project Explorer window. Dropping a page onto another page will place it under the hierarchy of the target page.

Dragging and dropping My New Page onto Orders page node.     My New Page moved under Orders page node.

The page can be moved from one node to another with Cut and Paste commands in the context menu. Use the Cut option on the context menu, and use Paste on the target page.

Cut context menu option on My New Page node.     Paste context menu option on Orders controller.

Holding CTRL while dropping directly onto a page will duplicate the page. If the drop location already has a page with the same name, the duplicated page name will be appended with a number. This can also be done by copying the first page, and then pasting the page in another location.

My New Page being copied onto Orders page node.     My New Page duplicate page node appended with a number.

Dropping a page on the right side of a target page node will place the page after the target. The mouse cursor will indicate where the page will be placed.

My New Page dropped after Orders page node.     My New Page dropped after Orders page node.

Dropping a page on the left side of a target page node will place the page before the target.

My New Page dropped before Orders page node.     My New Page page node placed before Orders in the Project Explorer.

Dragging and dropping a page with child nodes will move the child page nodes as well. Cutting or copying a page with children will also move or copy the entire group to the new location.

Reports page node with child pages dropped on Region page node.     Reports page node moved under Region along with all child pages.

Multiple pages can be selected by holding CTRL and clicking on pages. Clicking on a page node, holding SHIFT, and clicking another page node will select a range.

Customers, Employees, Categories, and Region page nodes selected.

Any drag and drop operations will be based on the order of selection. For example, the pages below were selected in the order of Customers, Employees, Categories, Region, and dropped to the right of Home. This resulted in the pages being reordered to Home, Region, Categories, Employees, and Customers.

Several selected pages dropped after Home node.     Several selected pages dropped after Home node.

Deleting Pages

Delete a page by right-clicking on the page and selecting Delete option.

Delete option for Customer Demographics page node.

You can also select the page(s) and press Delete on your keyboard.

Multiple page deletion prompt.

Renaming Page Nodes

The context menu of page nodes offers Rename option. If the command is activated on a top-level or child page, then the selected segment of the page Path will change. If the command is activated on a system page, then the Title of the page will change. The Path of a system page is always empty.

The following example shows renaming of the Customers / Orders / My New Page page node.

My New Page with Rename context menu option.     My New Page renamed.

The keyboard shortcut F2 will activate rename command on the selected page node. 

If you need to change the physical Name of the page, then select the page and change the Name property in the Designer window.

Hiding Pages from Navigation Menu

For certain pages, it may not be necessary to place them on the navigation menu. The Include in Menu option will remove the page from the menu.

Using the 'Exclude from Menu' context menu option for 'Customer Demographics' page.      'Customer Demographics' page is now excluded from the menu.

The page is still accessible via URL.

Friday, June 15, 2012PrintSubscribe
Implicit Filters with Dynamic Access Control Rules

The property Context Fields can pass values from the current record to the lookup data view. The value is passed in the format LookupFieldName=FieldNameOfThisView as an external filter. Multiple value mappings can be specified.

If LookupFieldName matches a data field in the lookup view, then an automatic “equals” filter will be applied to the lookup. If the LookupFieldName does not match, then the application framework will not perform filtering. A developer can use the passed external filter field value to create a filter expression or business rule implementing custom filtering.

Let’s create a business rule for a lookup view that takes advantage of values passed in the Context Fields property.

Navigate to the Orders page, and select an order. Create a new order detail, and activate the lookup for ProductID. The Northwind database has 77 products. All products will be available for selection in the Products lookup.

Lookup list of all 77 products available for selection.

Let’s exclude products already associated with order details of the existing order from this view.

Start the Project Designer. In the Project Explorer, switch to the Controllers tab. Double-click on Products controller node.

Products controller selected in the Project Explorer.

Change the Handler property:

Property New Value
Handler ProductsBusinessRules

Press OK to save the controller. Double-click on OrderDetails / Fields / ProductID field node.

ProductID field of OrderDetails controller.

Change the Context Fields property:

Property New Value
Context Fields ExistingOrderID=OrderID

Press OK to save the field. On the toolbar, press Exit to close the Project Designer, and click Generate.

When complete, click on the project name, and select Develop to open Visual Studio.

In the Solution Explorer of Visual Studio, double-click on ~\App_Code\Rules\ProductsBusinessRules.cs(.vb) file.

ProductsBusinessRules file in the Code On Time web application.

Replace the existing code with the following business rule:

C#:

using System;
using System.Data;
using System.Collections.Generic;
using System.Linq;
using MyCompany.Data;

namespace MyCompany.Rules
{
    public partial class ProductsBusinessRules : MyCompany.Data.BusinessRules
    {
        protected override void EnumerateDynamicAccessControlRules(string Products)
        {
            FieldValue orderId = SelectExternalFilterFieldValueObject(
                "ExistingOrderID");
            if (orderId != null && orderId.Value != null)
                RegisterAccessControlRule("ProductID",
                    "[ProductID] in (select ProductID from [Order Details] " +
                    "where OrderID = @OrderID)",
                    AccessPermission.Deny,
                    new SqlParam("@OrderID", orderId.Value));
        }
    }
}

Visual Basic:

Imports MyCompany.Data
Imports System
Imports System.Collections.Generic
Imports System.Data
Imports System.Linq

Namespace MyCompany.Rules

    Partial Public Class ProductsBusinessRules
        Inherits MyCompany.Data.BusinessRules
        Protected Overrides Sub EnumerateDynamicAccessControlRules(Products As String)
            Dim orderId As Object = SelectExternalFilterFieldValueObject(
                "ExistingOrderID")
            If (orderId IsNot Nothing AndAlso orderId.Value IsNot Nothing) Then
                RegisterAccessControlRule("ProductID",
                    "[ProductID] in (select ProductID from [Order Details] " +
                    "where OrderID = @OrderID)",
                    AccessPermission.Deny,
                    New SqlParam("@OrderID", orderId.Value))
            End If
        End Sub
    End Class
End Namespace

The business rule tries to locate the external filter field ExistingOrderID. If it is found, and the value is not null, then the business rule will register an access control rule. The access control rule will deny access to products that are matched to the “Order Details”.“ProductID” column if the column OrderID is equal to the value passed in ExistingOrderID filter field.

Save the file, and run the web application.

Navigate to the Orders page, and select an order. Note the number of order details belonging to the order.

Order Details child view displaying 3 records that belong to the selected order.

Create a new order detail. Click on (select) link in the Product Name lookup.

Product Name lookup on the New Order Details create form.

The Product lookup will open. There will be no products that are already ordered. In the example below, there are only 74 products displayed out of 77 products in the database.

Limited subset of 74 products displayed in the lookup.

Monday, June 11, 2012PrintSubscribe
Custom Date Format Strings

A date and time format string defines the text representation of a DateTime value that results from a formatting operation. It can also define the representation of a date and time value that is required in a parsing operation in order to successfully convert the string to a date and time. A custom format string consists of one or more custom date and time format specifiers. Any string that is not a standard date and time format string is interpreted as a custom date and time format string.

Let’s apply a custom format string to the OrderDate field of Orders controller.

Start the Project Designer. In the Project Explorer, double-click on Orders / Fields / OrderDate field node.

OrderDate field of Orders controller.

Change the Data Format String property:

Property Value
Data Format String 'The' d 'of' MMMM, yyyy.

Press OK to save the field. On the toolbar, press Browse.

Navigate to the Orders page. The Order Date values will be rendered in the custom date pattern.

Order Date with custom date format strings.

Below is a list of supported custom date format strings.

Format specifier

Description

Examples

"d"

The day of the month, from 1 through 31.

6/1/2009 1:45:30 PM –> 1
6/15/2009 1:45:30 PM -> 15

"dd"

The day of the month, from 01 through 31.

6/1/2009 1:45:30 PM –> 01
6/15/2009 1:45:30 PM -> 15

"ddd"

The abbreviated name of the day of the week.

6/15/2009 1:45:30 PM -> Mon (en-US)
6/15/2009 1:45:30 PM -> Пн (ru-RU)
6/15/2009 1:45:30 PM -> lun. (fr-FR)

"dddd"

The full name of the day of the week.

6/15/2009 1:45:30 PM -> Monday (en-US)
6/15/2009 1:45:30 PM -> понедельник (ru-RU)
6/15/2009 1:45:30 PM -> lundi (fr-FR)

"f"

The tenths of a second in a date and time value.

6/15/2009 13:45:30.617 –> 6
6/15/2009 13:45:30.050 -> 0

"ff"

The hundredths of a second in a date and time value.

6/15/2009 13:45:30.617 -> 61

6/15/2009 13:45:30.005 -> 00

"fff"

The milliseconds in a date and time value.

6/15/2009 13:45:30.617 –> 617
6/15/2009 13:45:30.0005 -> 000

"ffff"

The ten thousandths of a second in a date and time value.

6/15/2009 13:45:30.6175 –> 6175
6/15/2009 13:45:30.00005 -> 0000

"fffff"

The hundred thousandths of a second in a date and time value.

6/15/2009 13:45:30.61754 –> 61754
6/15/2009 13:45:30.000005 -> 00000

"ffffff"

The millionths of a second in a date and time value.

6/15/2009 13:45:30.617542 –> 617542
6/15/2009 13:45:30.0000005 -> 000000

"fffffff"

The ten millionths of a second in a date and time value.

6/15/2009 13:45:30.6175425 –> 6175425
6/15/2009 13:45:30.0001150 -> 0001150

"g", "gg"

The period or era.

6/15/2009 1:45:30 PM -> A.D.

"h"

The hour, using a 12-hour clock from 1 to 12.

6/15/2009 1:45:30 AM –> 1
6/15/2009 1:45:30 PM -> 1

"hh"

The hour, using a 12-hour clock from 01 to 12.

6/15/2009 1:45:30 AM –> 01
6/15/2009 1:45:30 PM -> 01

"H"

The hour, using a 24-hour clock from 0 to 23.

6/15/2009 1:45:30 AM –> 1
6/15/2009 1:45:30 PM -> 13

"HH"

The hour, using a 24-hour clock from 00 to 23.

6/15/2009 1:45:30 AM –> 01
6/15/2009 1:45:30 PM -> 13

"m"

The minute, from 0 through 59.

6/15/2009 1:09:30 AM –> 9
6/15/2009 1:09:30 PM -> 9

"mm"

The minute, from 00 through 59.

6/15/2009 1:09:30 AM –> 09
6/15/2009 1:09:30 PM -> 09

"M"

The month, from 1 through 12.

6/15/2009 1:45:30 PM -> 6

"MM"

The month, from 01 through 12.

6/15/2009 1:45:30 PM -> 06

"MMM"

The abbreviated name of the month.

6/15/2009 1:45:30 PM -> Jun (en-US)
6/15/2009 1:45:30 PM -> juin (fr-FR)
6/15/2009 1:45:30 PM -> Jun (zu-ZA)

"MMMM"

The full name of the month.

6/15/2009 1:45:30 PM -> June (en-US)
6/15/2009 1:45:30 PM -> juni (da-DK)
6/15/2009 1:45:30 PM -> uJuni (zu-ZA)

"s"

The second, from 0 through 59.

6/15/2009 1:45:09 PM -> 9

"ss"

The second, from 00 through 59.

6/15/2009 1:45:09 PM -> 09

"t"

The first character of the AM/PM designator.

6/15/2009 1:45:30 PM -> P (en-US)
6/15/2009 1:45:30 PM -> 午 (ja-JP)
6/15/2009 1:45:30 PM -> (fr-FR)

"tt"

The AM/PM designator.

6/15/2009 1:45:30 PM -> PM (en-US)
6/15/2009 1:45:30 PM -> 午後 (ja-JP)
6/15/2009 1:45:30 PM -> (fr-FR)

"y"

The year, from 0 to 99.

1/1/0001 12:00:00 AM –> 1
1/1/0900 12:00:00 AM –> 0
1/1/1900 12:00:00 AM –> 0
6/15/2009 1:45:30 PM -> 9

"yy"

The year, from 00 to 99.

1/1/0001 12:00:00 AM –> 01
1/1/0900 12:00:00 AM –> 00
1/1/1900 12:00:00 AM –> 00
6/15/2009 1:45:30 PM -> 09

"yyyy"

The year as a four-digit number.

1/1/0001 12:00:00 AM –> 0001
1/1/0900 12:00:00 AM –> 0900
1/1/1900 12:00:00 AM –> 1900
6/15/2009 1:45:30 PM -> 2009

"z"

Hours offset from UTC, with no leading zeros.

6/15/2009 1:45:30 PM -07:00 -> -7

"zz"

Hours offset from UTC, with a leading zero for a single-digit value.

6/15/2009 1:45:30 PM -07:00 -> -07

"zzz"

Hours and minutes offset from UTC.

6/15/2009 1:45:30 PM -07:00 -> -07:00

":"

The time separator.

6/15/2009 1:45:30 PM -> : (en-US)
6/15/2009 1:45:30 PM -> . (it-IT)
6/15/2009 1:45:30 PM -> : (ja-JP)

"/"

The date separator.

6/15/2009 1:45:30 PM -> / (en-US)
6/15/2009 1:45:30 PM -> - (ar-DZ)
6/15/2009 1:45:30 PM -> . (tr-TR)

'string'

Literal string delimiter.

6/15/2009 1:45:30 PM ('arr:' h:m t) -> arr: 1:45 P

%

Defines the following character as a custom format specifier.

6/15/2009 1:45:30 PM (%h) -> 1

Any other character

The character is copied to the result string unchanged.

6/15/2009 1:45:30 AM (arr hh:mm t) -> arr 01:45 A