Blog: Posts from September, 2008

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

Data Aquarium Framework includes a collection of JavaScript components that are rendering user interface in a web browser and are interacting with the server components of the framework. You can participate in the client-side life cycle by creating JavaScript event handlers that are responding to selected and executed events raised by Web.DataView component instances injected into the page by DataViewExtender server components.

Event selected is fired when a row is selected in the user interface. You can use get_selectedKey() method of Web.DataView component to find a primary key of a selected record.

Event executed is fired when a command has been executed. Event handler is provided with the result of execution on the server including auto-incremental primary key field values and error messages if any.

Let's explore these events by creating master-detail AJAX grid views that link Products to Suppliers in Northwind database.

Generate an Aquarium Express project with Code OnTime Generator from Northwind database and open this project in Visual Studio 2008 or Visual Web Developer 2008 Express Edition.

Add page Events.aspx to the root of the web site as shown in the sample below.

<%@ Page Language="C#" MasterPageFile="~/MasterPage.master" AutoEventWireup="true"
    CodeFile="Events.aspx.cs" Inherits="Events" Title="Events Demo" %>

<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="Server">

    <script type="text/javascript">
function pageLoad() {
    var dataView = Web.DataView.find('SuppliersExtender');
    if (dataView) {
        dataView.add_selected(onSupplierSelected);
        dataView.add_executed(onSupplierExecuted);
    }
}

var justInserted = false;

function onSupplierSelected(sender) {
    if (justInserted) 
        justInserted = false;
    else
        updateProductsVisibility(sender.get_lastCommandName() != 'New');
}
function onSupplierExecuted(sender, args) {
    switch (sender._lastArgs.CommandName) {
        case 'Insert':
            updateProductsVisibility(true);
            justInserted = true;
            break;
        case 'Delete':
            updateProductsVisibility(false);
            break;
    }
}
function updateProductsVisibility(visible) {
    Sys.UI.DomElement.setVisible($get('ProductsPanel'), visible);
}
    </script>

</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="Header1Placeholder" runat="Server">
    Client-Side Events
</asp:Content>
<asp:Content ID="Content3" ContentPlaceHolderID="Header2Placeholder" runat="Server">
    Northwind
</asp:Content>
<asp:Content ID="Content4" ContentPlaceHolderID="BodyPlaceholder" runat="Server">
    <div id="Suppliers" runat="server" />
    <aquarium:DataViewExtender ID="SuppliersExtender" runat="server" 
        Controller="Suppliers" TargetControlID="Suppliers" PageSize="5"/>
    <br />
    <div id="ProductsPanel" style="display:none">
        <div id="Products" runat="server" />
        <aquarium:DataViewExtender ID="ProductsExtender" runat="server" 
            Controller="Products" TargetControlID="Products" PageSize="5"
            FilterFields="SupplierID" FilterSource="SuppliersExtender" />
    </div>
</asp:Content>

Open this page in a browser. You will see that products are not displayed under the suppliers grid.

image

Click on any supplier row and the page will display a list of relevant products.  If you start adding a new supplier then the list of products will disappear. The list of products will show up again when you actually insert a supplier record. The list of products goes away when you delete a supplier.

image

How does this work?

Let's do a quick code walkthrough.

Element ProductsPanel is wrapped around the placeholder for Products. It doesn't matter if the DataViewExtender component is within the boundaries of the panel. Just make sure that the placeholder is hidden.

<div id="ProductsPanel" style="display:none">
    <div id="Products" runat="server" />
    <aquarium:DataViewExtender ID="ProductsExtender" runat="server" 
        Controller="Products" TargetControlID="Products" PageSize="5"
        FilterFields="SupplierID" FilterSource="SuppliersExtender" />
</div>

ASP.NET AJAX Extensions library automatically invokes JavaScript function pageLoad() when the runtime client components are instantiated and initialized. It works very much like Page_Load function in your server code, which is called when ASP.NET is ready to pass your a control over a page with all server components ready for use. Method Web.DataView.find will find an instance of JavaScript Web.DataView component that was injected into the page by SuppliersExtender server component. This is a convenient spot to assign event handlers of selected and executed events.

function pageLoad() {
    var dataView = Web.DataView.find('SuppliersExtender');
    if (dataView) {
        dataView.add_selected(onSupplierSelected);
        dataView.add_executed(onSupplierExecuted);
    }
}

Function onSupplierSelected will be called whenever a supplier record is selected by a user. This method is invoking updateProductsVisibility function and passes true as a parameter if the last executed action command is not New. We are also making sure that visibility of the products grid is not altered if we just have executed an insertion of a new supplier.

var justInserted = false;

function onSupplierSelected(sender) {
    if (justInserted) 
        justInserted = false;
    else
        updateProductsVisibility(sender.get_lastCommandName() != 'New');
}

Actions that cause an insertion or a deletion of a supplier will result in product details being displayed or hidden accordingly.

function onSupplierExecuted(sender, args) {
    switch (sender._lastArgs.CommandName) {
        case 'Insert':
            updateProductsVisibility(true);
            justInserted = true;
            break;
        case 'Delete':
            updateProductsVisibility(false);
            break;
    }
}

The actual update of products grid visibility is very simple. We are using standard JavaScript components of ASP.NET AJAX Extensions library to hide DOM element with ProductsPanel identifier.

function updateProductsVisibility(visible) {
    Sys.UI.DomElement.setVisible($get('ProductsPanel'), visible);
}

You can enhance this code to suit your own needs by interacting with div elements on your page, which will typically result in hiding and showing of arbitrary page fragments to create less cluttered and more intuitive user interface presentation in your AJAX ASP.NET applications created with Code OnTime Generator.

Sunday, September 28, 2008PrintSubscribe
Restricting Read/Write Access To Fields

Data Aquarium Framework provides multiple options to allow precise control of read and write access to data fields displayed in grid and form views.

Generate an Aquarium Express application with Code OnTime Generator and Northwind database. Open ~/Controllers/Products.xml and follow instructions to try various methods of restricting user's ability to change the UnitPrice field values.

ReadOnly Attribute

If you want to prevent your users from changing field values then defining readOnly attribute on fields in data controller will do the trick.

<field name="UnitPrice" type="Decimal" default="(0)" 
  label="Unit Price" readOnly="true"/>

This is how the field is rendered in the grid view of sample application when you try to edit any row.

image

Notice that readOnly attribute will affect all grid and form views in the data controller.

Duplicate Field With ReadOnly Attribute

Sometimes you may want to prevent users from editing field in a grid view but still want to allow editing in forms. A simple solution is to define an additional field in your SQL query with matching field element adorned with readOnly attribute.

Here is how you can change the query that retrieves Products. The query includes a duplicate field that selects UnitPrice with an alias UnitPriceReadOnly.

select
    "Products"."ProductID" "ProductID"
    ,"Products"."ProductName" "ProductName"
    ,"Products"."SupplierID" "SupplierID"
    ,"Supplier"."CompanyName" "SupplierCompanyName"
    ,"Products"."CategoryID" "CategoryID"
    ,"Category"."CategoryName" "CategoryCategoryName"
    ,"Products"."QuantityPerUnit" "QuantityPerUnit"
    ,"Products"."UnitPrice" "UnitPrice"
    ,"Products"."UnitPrice" "UnitPriceReadOnly"
    ,"Products"."UnitsInStock" "UnitsInStock"
    ,"Products"."UnitsOnOrder" "UnitsOnOrder"
    ,"Products"."ReorderLevel" "ReorderLevel"
    ,"Products"."Discontinued" "Discontinued"
from "dbo"."Products" "Products"
    left join "dbo"."Suppliers" "Supplier" 
      on "Products"."SupplierID" = "Supplier"."SupplierID"
    left join "dbo"."Categories" "Category" 
      on "Products"."CategoryID" = "Category"."CategoryID"

Add a matching field UnitPriceReadOnly to the fields section of the data controller.

<field name="UnitPriceReadOnly" type="Decimal" default="(0)" 
  label="Unit Price"  readOnly="true"/>

Next change the definition of grid1 view to prevent users from editing the field by replacing reference to UnitPrice with the reference to UnitPriceReadOnly.

<view id="grid1" type="Grid" commandId="command1" label="Products">
  <headerText>This is a list of products. </headerText>
  <dataFields>
    <dataField fieldName="ProductName" columns="40" />
    <dataField fieldName="SupplierID" aliasFieldName="SupplierCompanyName" />
    <dataField fieldName="CategoryID" aliasFieldName="CategoryCategoryName" />
    <dataField fieldName="QuantityPerUnit" columns="20" />
    <dataField fieldName="UnitPriceReadOnly" 
      dataFormatString="c" columns="15" />
    <dataField fieldName="UnitsInStock" columns="15" />
    <dataField fieldName="UnitsOnOrder" columns="15" />
    <dataField fieldName="ReorderLevel" columns="15" />
    <dataField fieldName="Discontinued" />
  </dataFields>
</view>

Form views editForm1 and createForm1 will retain references to the original field UnitPrice, which allows users to make price adjustments in form mode only.

WriteRoles Attribute

A superior approach is to rely on the security infrastructure of ASP.NET and its support in Data Aquarium Framework.

Attribute roles defined on a field will limit visibility of the field in views to users with the specified roles. Field writeRoles will prevent users from changing the field if the user's role is not on a comma-separated list.

If you add this attribute as shown in the snippet then the result will be a read-only display to all users that do not have Admin role.

<field name="UnitPrice" type="Decimal" default="(0)" 
  label="Unit Price" writeRoles="Admin"/>

The sample application generated with Aquarium Express project is relying on Windows authentication by default. Role Admin is not defined in a typical Windows configuraiton and this will cause the UnitPrice to be displayed as read-only in all grid and form views of Products data controller.

Most Windows user accounts belong to Users group. If you replace Admin with Users then an editable version of UnitPrice field is presented.

The same role level access is available if you switch your application to forms authentication or create a custom role and/or user manager.

You can read more about field-level security in Data Aquarium Framework applications in the post Using "roles" And "writeRoles" Attributes With Fields And Actions.

Sunday, September 28, 2008PrintSubscribe
ASP.NET AJAX Globalization

All web application projects generated by Code OnTime Generator are built on standard ASP.NET infrastructure. Excellent globalization support is an element of ASP.NET that can be quickly turned on in a matter of minutes. Let's give it a try.

Generate an Aquarium Express application with Northwind database and wait until it shows up in a web browser. Select Orders data controller in a drop down of the default page. A view similar to the one below will be presented.

image

Notice that by default Order Date, Required Date, Shipped Data, and Freight are using formatting accepted in United States. Dates are displayed in mm/dd/yyyy format. Currency values are displayed with a leading symbol of US dollar.

Open the generated web site in Visual Studio or Web Developer Express and select MasterPage.master in Solution Explorer. Find markup of asp:ScriptManager and add EnableScriptGlobalization attribute as shown in the snippet.

<asp:ScriptManager ID="sm" runat="server" ScriptMode="Release" 
    EnableScriptGlobalization="true"/>

Next bring up web.config configuration file of your web site and change globalization section as follows.

<globalization culture="en-gb" uiCulture="en-gb" />

Run the web site and select Orders option in data controller drop down one more time.

image

Now you can see that all dates are displayed in dd/mm/yyyy format common to European countries. Values in Freight column are also presented with a symbol of British pound.

The same consistent display is available when users are editing data in any grid or form view of Aquarium Express or Data Aquarium Framework applications.

image

You can read more about globalization and localization support in ASP.NET at http://msdn.microsoft.com/en-us/library/c6zyy3s9.aspx.

Continue to Data Field Aggregates