Tips and Tricks

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
Tips and Tricks
Friday, August 15, 2014PrintSubscribe
Improving Performance Of Reports in ASP.NET 4.0 and 4.5 Applications

Microsoft Report Viewer is the lightweight reporting engine used by generated apps to produce data reports in PDF, Word, Excel, and TIFF format. A generated app creates an in-memory table of data sorted and filtered according to the end user criteria. The data table is passed to Report Viewer to produce a report. The design template of the report is either created on-the-fly by the application framework or supplied by a developer at design time.

Report Viewer allows including formulas written in Visual Basic in the definitions of property expressions in various elements of a report template. The report formulas from the template are compiled to executable code by Report Viewer. If an ASP.NET web application tries to create a  report with the help of Microsoft Report Viewer, then certain security requirements must be satisfied. The formulas compiled by Report Viewer must run in “sandbox” environment.

ASP.NET security configuration has changed starting with ASP.NET 4.0. Now the sandbox of Report Viewer is required to jump through many hoops in order to produce a report. This results in poor performance of reports  on large datasets requiring significantly more time to complete rendering.

A simple solution exists to overcome this problem in an app created with Code On Time.

1) Select the project name on the start page of the app generator and choose Settings.

2) Proceed to Web Server Configuration and paste the following snippet into Web.Config modification instructions box:

AppendChild: /configuration/system.web

<trust legacyCasModel="true"/>

3) Click Finish and regenerate the project. A new <trust…/> entry will be created in the configuration file of application.

Now the reporting performance will become significantly improved.

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.

Wednesday, May 7, 2014PrintSubscribe
Display Density in Touch UI Apps

A size of user interface elements is an important consideration for any application. Touch UI provides a user-configurable setting Display Density that allows changing the density of text to satisfy personal preferences.

Application automatically selects Comfortable display density on mobile devices to provide a touch-friendly user interface.

Display density is set to Compact on desktop devices that do not have a touch-enabled screens.

Choose option Menu / Settings / Display Density / Compact to change the display density to Compact.

The screen shots show Comfortable and Compact lists of products side-by-side on iPhone 5.

A list of products displayed in 'Comfortable' density in an app with Touch UI on iPhone 5. A list of products displayed in 'Compact' density in an app with Touch UI on iPhone 5.

These screen shots compare Comfortable and Condensed lists of products.

A list of products displayed in 'Comfortable' density in an app with Touch UI on iPhone 5. A list of products displayed in 'Condensed' density in an app with Touch UI on iPhone 5.

This is a screen shot of the same product list on Surface 2 displayed with Compact density.

A list of products displayed on Surface 2 tablet in 'Compact' density in an app with Touch UI.

Condensed display density works best on desktop computers. Mouse pointer makes it easier to hit smaller user interface elements.  This display density must be explicitly selected by a user.

Next screen shot shows a “condensed” list of products on a desktop computer displayed in IE 11 on Windows 7.

A list of products displayed with 'Condensed' density on a desktop computer in IE11.

This is a “condensed’' rendering of products shown in “Grid” style in IE 11 on Windows 7.

A list of products displayed with 'Condensed' density and 'Grid' style on a desktop computer in IE11.