Blog

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
Monday, June 3, 2013PrintSubscribe
Handling the “Report…” Action

Code On Time web applications support out-of-the-box reporting capabilities that require zero programming.

Standard Report Actions

All data views offer four standard actions that yield a different output.

  • Action “ReportAsPdf” will render the data presented to end users as a Adobe PDF document. The shorthand action “Report” will produce the same result. This type of report requires a compatible software installed on the client computer to view and print the report output. You can download free Adobe Acrobat Reader at at http://get.adobe.com/reader.
     
  • Action “ReportAsImage” creates a TIFF image file, which requires a compatible software installed on the client. TIFF format supports multiple pages and is a perfect alternative to PDF. The quality of output in PDF and TIFF formats is equivalent.
     
  • Action “ReportAsWord” renders a report as a Microsoft Word document with a high-quality output. In some instances, the output is less precise than the output produced by the action “ReportAsImage” and “ReportAsPdf”.
     
  • Action “ReportAsExcel” produces a Microsoft Excel spreadsheet that offer a lesser quality output due to rendering restrictions of Excel files.

If a user  requests a “Report...” action then a report is rendered on the server with the help of Microsoft Report Viewer. The output is streamed to the client browser. Typically a prompt is displayed before a compatible installed software viewer will be activated. Users also have an option to save the output locally. If a viewer is not installed on the client computer, then the prompt to save the file is the only option.

Code On Time web applications execute various server calls off-band to provide a smooth Web 2.0 user experience. Modern web browsers make sure to prevent all sorts of popups initiated by the scripts embedded in the web pages. The client library makes use of correct techniques to process reports on the server without triggering popup blockers.

Custom Report Action Handlers

Code On Time web applications created with version 6.0.0.19 or higher allow developers to perform custom processing of reporting actions in business rules. There are several reasons that may require an execution of  custom code that must precede or override the standard report rendering logic:

  • The data must be “prepared” before a report is rendered.
  • The report request must be logged.
  • An external report rendering engine is available. The custom code will redirect the report request to such an engine.
  • A special report preview page needs to be displayed.
  • A custom report building code must execute. The custom code replaces the standard report rendering logic.

To modify the behavior of the Report action, create a business rule and implement methods to handle the corresponding “Report...” actions.

Passing Action To An External URL

Start the Project Designer. In the Project Explorer, switch to the Controllers tab. Right-click on Customers / Actions node, and press New Action Group.

Adding a new action group to Customers controller.

Assign the following value:

Property Value
Scope Action Column

Save the new action group. Right-click on Customers / Actions / ag100 (ActionColumn) and press New Action.

Adding a new action to action group 'ag100'.

Assign these values:

Property Value
Command Name Report
Command Argument _blank

Press OK to save. Right-click on Customers / Business Rules node, and press New Business Rule.

Adding a new business rule to Customers controller.

Assign the following values:

Property Value
Type C# / Visual Basic
Command Name Report
Command Argument _blank
Phase Execute

Save the business rule. Press Browse on the toolbar to generate the business rule file.

When complete, right-click on Customers / Business Rules / Report, _blank (Code / Execute) – r100 node and press Edit Rule in Visual Studio.

Opening the business rule file in Visual Studio.

The file will be opened in Visual Studio. Replace the existing code base with the following:

C#:

using System;
using MyCompany.Data;

namespace MyCompany.Rules
{
    public partial class CustomersBusinessRules : MyCompany.Data.BusinessRules
    {
        [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)
        {
            // Redirect user to another URL
            Result.NavigateUrl = String.Format(
                "~/Pages/Customers.aspx?CustomerID={0}&_controller=Customers" +
                "&_commandName=Select&_commandArgument=editForm1",
                customerID);
        }
    }
}

Visual Basic:

Imports MyCompany.Data
Imports System

Namespace MyCompany.Rules
    
    Partial Public Class CustomersBusinessRules
        Inherits MyCompany.Data.BusinessRules
        <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)
            ' Redirect user to another URL
            Result.NavigateUrl = String.Format( _
                "~/Pages/Customers.aspx?CustomerID={0}&_controller=Customers" + _
                "&_commandName=Select&_commandArgument=editForm1",
                customerID)
        End Sub
    End Class
End Namespace

Save the file. The business rule will use the ID of the selected customer to compose a URL relative to the application. The URL will open in a new browser window and will force the application to select a customer with the specified ID.

The new window will open if your have entered the command argument as “_blank” when defining the action in Project Designer. If action command argument has been left blank then the new URL will replace the page in the web browser. Users will have an option to return to the previous page using the browser’s Back button.

Switch back to the web app open in the browser window and navigate to Customers page. A new action button will be present in the leftmost column.

'Report' action in the leftmost action column.

Click on the Report button - a new browser window will open. You can see that the address bar is reflecting values from the selected customer.

New browser window opened with URL parameters from the previously selected customer.

Our web application is using its own capabilities to present the data with the help of data controller URL parameters. You can redirect the report action to a generic web request handler or to a web-enabled report server such as Crystal Reports or Microsoft SQL Server Reporting Services.

Overriding the Report Action

Switch back to the Project Designer. Right-click on Customers / Business Rules and press New Business Rule.

Adding a new business rule to Customers controller.

Use the following configuration:

Property Value
Type C# / Visual Basic
Command Name ReportAsImage
Phase Execute

Save the business rule. Right-click on Customers / Business Rules / ReportAsImage (Code / Execute) – r101 node, and press Edit Rule in Visual Studio.

Opening the business rule file in Visual Studio.

Replace the code base with the following:

C#:

using System;
using MyCompany.Data;
using System.IO;

namespace MyCompany.Rules
{
    public partial class CustomersBusinessRules : MyCompany.Data.BusinessRules
    {
        [Rule("r101")]
        public void r101Implementation(string customerID, 
            string companyName, 
            string contactName, 
            string contactTitle, 
            string address, 
            string city, 
            string region, 
            string postalCode, 
            string country, 
            string phone, 
            string fax)
        {
            PreventDefault();
            // return the same image in response to all "Report..." commands
            Context.Response.Clear();
            Context.Response.ContentType = "image/jpeg";
            Context.Response.AddHeader("Content-Disposition",
                String.Format("attachment;filename={0}.jpg", customerID));
            byte[] reportData =
                File.ReadAllBytes(@"C:\Users\Public\Public Pictures\Sample Pictures\Koala.jpg");
            Context.Response.AddHeader("Content-Length", reportData.Length.ToString());
            Context.Response.OutputStream.Write(reportData, 0, reportData.Length);
        }
    }
}

Visual Basic:

Imports MyCompany.Data
Imports System
Imports System.IO

Namespace MyCompany.Rules

    Partial Public Class CustomersBusinessRules
        Inherits MyCompany.Data.BusinessRules
        <Rule("r101")> _
        Public Sub r101Implementation(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)
            PreventDefault()
            'return the same image in response to all "Report..." commands
            Context.Response.Clear()
            Context.Response.ContentType = "image/jpeg"
            Context.Response.AddHeader("Content-Disposition", _
                String.Format("attachment;filename={0}.jpg", customerID))
            Dim reportData As Byte() = _
                File.ReadAllBytes("C:\Users\Public\Public Pictures\Sample Pictures\Koala.jpg")
            Context.Response.AddHeader("Content-Length", reportData.Length.ToString())
            Context.Response.OutputStream.Write(reportData, 0, reportData.Length)
        End Sub
    End Class
End Namespace

Save the file.

This business rule takes control over the report rendering completely.

First, the method cancels out the default reporting logic at the very beginning by calling PreventDefault. The method uses the customer ID to assign the file name to the output. Next, it reads the file C:\Users\Public\Public Pictures\Sample Pictures\Koala.jpg and streams it out. If you are reproducing this sample on a Windows 7 computer then there is not need to change the code . Otherwise change the path to the image file accordingly.

In a real-world application you can produce any sort of output using custom code.

Switch back to the browser, navigate to Customers page and select a customer. Choose Report | Multipage Image on the action bar.

Triggering the ReportAsImage action from the action bar.

The custom method will execute and you will  be prompted to download the file AROUT.jpg.

Browser prompting to download a file.

Click Open and the default image viewer will start.

The koala image is displayed. The file name is inherited from the CustomerID.

If you select any other customer and choose the same action bar option then exactly the same image will be downloaded but the file name will reflect the primary key of the selected customer.

In a real-world applications you will likely stream other formats of output such as PDF or custom Microsoft Office documents using 3rd party reporting software.

Sunday, June 2, 2013PrintSubscribe
Globalization and Localization

Globalization is the process of designing and developing applications that function for multiple cultures. Localization is the process of customizing your application for a given culture and locale. The topics in this section describe how to create ASP.NET web applications that can be adapted to different languages and cultures.

Learn more about globalization and localization of ASP.NET web applications at http://msdn.microsoft.com/en-us/library/c6zyy3s9.aspx.

Globalization

Code On Time web app generator allows explicit definition of globalization options in the Project Wizard.

Globalization and Localization page of Project Wizard.

Each application has a default culture. Unlimited edition of Code On Time allows specifying additional cultures. The browser culture will be detected and used, if available. The user may also manually specify the culture using the Language selector dropdown in the top right corner of the web app.

Localization

At run-time, the client library automatically replaces text elements wrapped in “localization tokens” when the culture is different from the default. The translations are stored as text constants in resource files. The client library matches the culture to the end of the text file name. For example, when the culture is changed to Canadian English, the client library will find translations in files that end with “en-CA.txt”.

For example, let’s examine the standard Welcome user control that is present in every web app. Notice that each text block is wrapped in a descriptive word surrounded by the carat (^) character.

<div style="padding-left: 8px">
    <div class="ParaInfo">
        ^SignInInstruction^Sign in to access the protected site content.^SignInInstruction^
    </div>
    <div class="ParaHeader">
        ^SignInHeader^Instructions^SignInHeader^
    </div>
    <div class="ParaText">
        ^SignInPara1^Two standard user accounts are automatically created when application is initialized if membership option has been selected for this application.^SignInPara1^
    </div>

    <div class="ParaText">
        ^SignInPara2^The administrative account <b>admin</b> is authorized to access all areas of the web site and membership manager. The standard <b>user</b> account is allowed to access all areas of the web site with the exception of membership manager.^SignInPara2^
    </div>

    <div class="ParaText">
        ^SignInPara3^Move the mouse pointer over the link <i>Login to this web site</i> on the right-hand side at the top of the page and sign in with one of the accounts listed below.^SignInPara3^
    </div>

    <div class="ParaText">
        <div style="border: solid 1px black; background-color: InfoBackground; padding: 8px; float: left;">
            ^AdminDesc^Administrative account^AdminDesc^:<br />
            <b title="User Name">admin</b> / <b title="Password">admin123%</b>
            <br />
            <br />
            ^UserDesc^Standard user account^UserDesc^:<br />
            <b title="User Name">user</b> / <b title="Password">user123%</b>
        </div>
        <div style="clear: both; margin-bottom: 8px"></div>
    </div>
</div>

Let’s provide our own translations for the “en-CA” culture that will replace the text wrapped in tags.

Customizing Localization

Start the web app generator and click on the project name. Select Settings, and then click on Globalization and Localization. In the Supported Culture Sets text box, enter the following:

Property Value
Supported Culture Sets en-US; en-CA;

Press Finish and regenerate the web app. When complete, click on the project name and press Open to open the project folder. In the search box, type in “en-CA.txt”. This will reveal all translation files for the “en-CA” culture.

All localization files for 'en-CA' culture.

Open the file “Welcome.ascx.en-CA.txt”. Notice that each element is wrapped in named tags surrounded by the carat (^) symbol. The client library will match the tags with those in the Welcome user control and replace the text at run-time.

Make the highlighted changes:

*******************************************************************************
Your application uses this file to locate resource strings defined
in Welcome.ascx project item.

Replace the text between localization brackets as needed.
*******************************************************************************

^AdminDesc^This is the Canadian Administrative account^AdminDesc^

^SignInHeader^Canadian Instructions^SignInHeader^

^SignInInstruction^Sign in to access the protected site content.^SignInInstruction^

^SignInPara1^Two standard user accounts are automatically created when application is initialized
    if membership option has been selected for this application.^SignInPara1^

^SignInPara2^The administrative account <b>admin</b> is authorized to access all areas of the
    web site and membership manager. The standard <b>user</b> account is allowed to
    access all areas of the web site with the exception of membership manager.^SignInPara2^

^SignInPara3^Move the mouse pointer over the link <i>Login to this web site</i> on the right-hand side
    at the top of the page and sign in with one of the accounts listed below.^SignInPara3^

^UserDesc^Standard user account^UserDesc^

Save the file, and switch to the application open in the browser. Refresh the Home page. Use the Language dropdown in the top-right corner to change to English (Canada). Note that the changes made previously have been applied to the text in the Welcome control on the right side of the page.

Custom translations are applied for the Welcome user control.

In addition to any text translations, any money or date formatting for the culture will be used as well. If the culture supports right-to-left, the website will be formatted accordingly.

Preserving Localization Between Code Generation Library Updates

Code generation library updates automatically replace the previous versions of the code generation files. A backup of the web app can be restored from [My Documents]\Code OnTime\Backup when it happens. You can create a copy of your localizations and restore them after each update.

You can also submit the completed localization file sets to Code On Time for inclusion in the general distribution of the code generation library. The localization file sets will be shared with the community and will get installed automatically with each update. If you have localizations to contribute, please zip up the files and submit a ticket.

Sunday, June 2, 2013PrintSubscribe
Tall And Wide Pages

The picture below shows the standard page layout of a Web Site Factory application. The page features a membership bar at the top, followed by a page header and logo, a bar with application menu system, a page title, and page path. The is also a side bar on the left side of the page.

Employees page with standard page layout.

What if you want to maximize the real estate of the page and eliminate some of the standard page elements?

Using Custom CSS Classes

Start the Project Designer. In the Project Explorer, double-click on the Employees page node. Assign the following value:

Property Value
Custom Style Tall Wide HomePage

On the toolbar, press Browse. Class Tall hides the menu bar at the top of the page, class Wide hides the side bar and class HomePage replaces the yellow background with the standard home page background. These classes can be used in any combination.

Employees page with 'Tall' and 'Wide' custom class stying.

Maximize Real Estate of The Page

If the Tall and Wide custom classes are not small enough for the requirements, the page may be reduced even further with a user control.

In the Project Explorer, right-click on Employees / container1 node, and press New Control.

Adding a new control to 'container1' of Employees page.

Next to the User Control lookup, click on New User Control icon.

Creating a new user control.

Assign the user control a name:

Property Value
Name Maximizer

Press OK to create the user control. Press OK again to instantiate the user control on the Employees page.

On the toolbar, press Browse to generate the user control file. When complete, right-click on Employees / container1 / control1 – Maximizer and press Edit in Visual Studio.

Editing the control in Visual Studio.

The user control file will open in Visual Studio. Replace the existing code with the following:

C#:

<%@ Control Language="C#" AutoEventWireup="true" CodeFile="Maximizer.ascx.cs" Inherits="Controls_Maximizer" %>
<script type="text/C#" runat="server">
    protected void Page_Init(object sender, EventArgs e)
    {
        Page.Header.Controls.Add(new LiteralControl(
            "<style type=\"text/css\">" +
            "body {padding:0px!important;}" +
            // hide the membership bar
            "div.MembershipBar, div.MembershipBarPlaceholder {display:none!important;}" +
            // hide the page header and logo
            "div#PageHeader{display:none!important;}" +
            // hide the page title
            "#PageHeaderLeftSide,#PageHeaderContent," +
            "#PageHeaderRightSide{background-image:none!important}" +
            "#PageHeaderContent div.Title {display:none!important;}" +
            // hide the page path
           "#PageHeaderContent .SiteMapPath {display:none!important;}" +
            "</style>"));
    }
</script>

Visual Basic:

<%@ Control Language="VB" AutoEventWireup="false" CodeFile="Maximizer.ascx.vb" Inherits="Controls_Maximizer" %>
<script type="text/VB" runat="server">
    Protected Shadows Sub OnInit(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load
        Page.Header.Controls.Add(New LiteralControl(
            "<style type=""text/css"">" +
            "body {padding:0px!important;}" +
            "div.MembershipBar, div.MembershipBarPlaceholder {display:none!important;}" +
            "div#PageHeader{display:none!important;}" +
            "#PageHeaderLeftSide,#PageHeaderContent," +
            "#PageHeaderRightSide{background-image:none!important}" +
            "#PageHeaderContent div.Title {display:none!important;}" +
           "#PageHeaderContent .SiteMapPath {display:none!important;}" +
            "</style>"))
    End Sub
</script>

Switch back to the browser, and refresh the Employees page. Note that all page elements except the views and any page body styles have been hidden.

Employees page with all page elements hidden except the body.

Continue to Complex Queries