ASP.NET Code Generator

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
ASP.NET Code Generator
Friday, May 21, 2010PrintSubscribe
Sort and Filter

Web Site Factory applications can now use declarative sort and filter expressions on data views. This feature allows effecting just-in-time ORDER BY and WHERE clause automatically created by the application framework at runtime without the need to modify the command.

Multiple views can use the same command and offer different sort and filter expression.

Sort Expression

Run Code OnTime Generator and select your project. Click Design button and select the data controller. Activate Views tab and choose grid1. The following screen is presented if you edit the view and enter the sort expression. Sort expression is a list of data field names of this view, each followed by optional asc or desc suffix.

Here is how the grid1 view looks if you enter the sort expression in the application created from the Northwind database.

image

If you save the changes and preview the data controller in the Test Bench then the initial list of customers will look like then one in the picture.

image

The actual SQL  statement executed at runtime looks like the one below. Notice that ORDER BY in the common table expression has been expanded with the actual table column names represented by Country and CompanyName fields.

with page_cte__ as (
select
row_number() over (order by "Customers"."Country" ,"Customers"."CompanyName"  desc) as row_number__
,"Customers"."CustomerID" "CustomerID"
,"Customers"."CompanyName" "CompanyName"
,"Customers"."ContactName" "ContactName"
,"Customers"."ContactTitle" "ContactTitle"
,"Customers"."Address" "Address"
,"Customers"."City" "City"
,"Customers"."Region" "Region"
,"Customers"."PostalCode" "PostalCode"
,"Customers"."Country" "Country"
,"Customers"."Phone" "Phone"
from
"dbo"."Customers" "Customers"

)
select * from page_cte__ where row_number__ > 0 and row_number__ <= 5

Filter Expression

Filter expression must be compatible with the back-end database server syntax. Data field names used in filter are automatically expanded into appropriate SQL expressions as defined in command.

Suppose you enter the following filter expression in the Northwind sample.

image

This filter expression will result in the following expression executed by the framework at runtime.

with page_cte__ as (
select
row_number() over (order by "Customers"."Country" ,"Customers"."CompanyName"  desc) as row_number__
,"Customers"."CustomerID" "CustomerID"
,"Customers"."CompanyName" "CompanyName"
,"Customers"."ContactName" "ContactName"
,"Customers"."ContactTitle" "ContactTitle"
,"Customers"."Address" "Address"
,"Customers"."City" "City"
,"Customers"."Region" "Region"
,"Customers"."PostalCode" "PostalCode"
,"Customers"."Country" "Country"
,"Customers"."Phone" "Phone"
from
"dbo"."Customers" "Customers"

where
(
ContactTitle='Owner')
)
select * from page_cte__ where row_number__ > 0 and row_number__ <= 5

The filter expression is inserted verbatim in the command text.

Filter expressions support parameters. Parameters must be prefixed by "@" or ":" symbol. You must implement a business rules class for the data controller with a property or field that matches the parameter name.

If you modify the filter expression as follows then additional configuration steps are needed.

ContactTitle = @ContactTitleFilter

First you need to define the name of the business rules class for your data controller. We have entered CustomerRules in the field Handler as displayed in the screen shot.

image

Then you need to generate the application. This will create the business rules class in the file ~/App_Code/Rules/CustomerRules.cs(vb).

The file will not be overwritten if you re-generate the code next time. It is safe to place your custom business logic in it. The sample filter implementation of property ContactTitleFilter in C# is performing conditional filtering of customers by Contact Title.

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

namespace MyCompany.Rules
{
    public partial class CustomerRules : MyCompany.Data.BusinessRules
    {
        public string ContactTitleFilter
        {
            get
            {
                if (Context.User.IsInRole("Administrators"))
                    return "Owner";
                else
                    return "Sales Agent";
            }
        }
    }
}

This is the screen shot of Customers screen presented to user account user/user123%.

image

Saturday, March 27, 2010PrintSubscribe
Integrating ELMAH in Code OnTime Projects

Q. I have another question. I just implemented ELMAH into my solution and
am having some difficulty because every time I use the designer and
regenerate the solution the Elmah configuration entries get
overwritten in Web.Config. I'm sure others have run into this before.
How would you suggest I remediate this issue?

Arthur Djavairian

A. You can configure the project to execute custom Web.Config modification instructions as described at /blog/2010/03/customizing-webconfig.html.

ELMAH (Error Logging Modules and Handlers) is an application-wide error logging facility that is completely pluggable. It can be dynamically added to a running ASP.NET web application, or even all ASP.NET web applications on a machine, without any need for re-compilation or re-deployment.

Arthur has shared with us his configuration settings.

The following is the markup to add ELMAH error logging to a Code OnTime project.  Make sure to copy the instructions including the text in bold.

AppendChild: /configuration/configSections

              <sectionGroup name="elmah">
                       <!-- NOTE! If you are using ASP.NET 1.x then remove the
                requirePermission="false" attribute from the section
                elements below as those are only needed for
                partially trusted applications in ASP.NET 2.0 -->
                       <section name="security" requirePermission="false" type="Elmah.SecuritySectionHandler, Elmah"/>
                       <section name="errorLog" requirePermission="false" type="Elmah.ErrorLogSectionHandler, Elmah"/>
                       <section name="errorMail" requirePermission="false" type="Elmah.ErrorMailSectionHandler, Elmah"/>
                       <section name="errorFilter" requirePermission="false" type="Elmah.ErrorFilterSectionHandler, Elmah"/>
                       <section name="errorTweet" requirePermission="false" type="Elmah.ErrorTweetSectionHandler, Elmah"/>
               </sectionGroup>

InsertAfter: /configuration/connectionStrings

       <elmah>
               <security allowRemoteAccess="1"/>
               <!--
           Use to log errors to Microsoft SQL Server 2000 or 2005
           using ASP.NET 2.0. Set value of connectionStringName attribute
           to the name of the connection string settings to use from
           the <connectionStrings> section.
       -->
               <errorLog type="Elmah.SqlErrorLog, Elmah" connectionStringName="SimplePaymentPlans"/>
       </elmah>

AppendChild: /configuration/system.web/httpHandlers


<add verb="POST,GET,HEAD" path="elmah.axd" type="Elmah.ErrorLogPageFactory, Elmah"/>

AppendChild: /configuration/system.web/httpModules

<add name="ErrorLog" type="Elmah.ErrorLogModule, Elmah"/>

AppendChild: /configuration

   <location path="elmah.axd">
       <system.web>
           <authorization>
               <allow roles="Administrators"/>
               <deny users="*" />
           </authorization>
       </system.web>
   </location>

Thursday, March 25, 2010PrintSubscribe
Customizing Web.Config

Code OnTime Generator automatically creates a web.config file for each generated application to ensure that all requested application features will function properly. Every code generation session automatically erases the previous version of the web.config.

You can add custom-tailored web.config entries that will complement the standard configuration file created by code generator.

Run the code generator and select your project. Follow the steps in the project wizard until you reach the Web Server topic. Under the label Web.Config modification instructions you can enter the instructions that will force the code generator to customize the generated web.config during each code generation session.

image

AppendChild Instruction

Suppose you want to add application settings that will drive the web site behavior. Instruction AppendChild will insert two add elements as children of the appSettings element. Note that text in bold is a part of modification instruction.

AppendChild: /configuration/appSettings

<add key="Setting1" value="Value1" />
<add key="Setting2" value="Value2" />

Here is the snippet of the generated web.config:

<configuration>
  <configSections>
    ...........
  </configSections>
  <appSettings>
    <add key="Setting1" value="Value1" />
    <add key="Setting2" value="Value2" />
  </appSettings>
  <connectionStrings>
    <add name="MyCompany" connectionString="Data Source=.;Initial Catalog=Northwind;Integrated Security=True;" providerName="System.Data.SqlClient" />
  </connectionStrings>
  .............

The instruction must be followed immediately by a “:”character, a space, and XPath expression that directs the code generator to the existing section of the configuration file.

Don’t be deterred if you are not familiar with XPath. Think of the web.config configuration elements as files and folders in a system of directories. XPath expression is simply a path to an element. Use forward slash to prefix every “file name” on the path and you will do just fine. In our example the instruction is AppendChild and the XPath expression is /configuration/appSettings.

The instruction line is separated with at least one blank line from the actual XML snippet that must be inserted into the configuration file.

You can enter as many instructions and snippets as needed. Simply make sure to have a least one blank line separating any snippet from the next instruction.

InsertBefore and InsertAfter Instruction

Instructions InsertBefore and InsertAfter will allow insertion of a sibling snippet on the same level as the element address by the  XPath expression of the instruction. InsertBefore will insert a snippet above the target element, while InsertAfter will create a sibling snippet right after the target element.

Consider this example:

AppendChild: /configuration/appSettings

<add key="Setting1" value="Value1" />
<add key="Setting2" value="Value2" />

InsertBefore: /configuration/appSettings/add[2]

<add key="Setting3" value="Value3" />

Here is how the web.config will look if you generate your project:

<configuration>
  <configSections>
    .....................
  </configSections>
  <appSettings>
    <add key="Setting1" value="Value1" />
    <add key="Setting3" value="Value3" />
    <add key="Setting2" value="Value2" />
  </appSettings>
  <connectionStrings>
    <add name="MyCompany" connectionString="Data Source=.;Initial Catalog=Northwind;Integrated Security=True;" providerName="System.Data.SqlClient" />
  </connectionStrings>
  ..................

Notice that InsertBefore instruction uses XPath expression /configuration/appSettings/add[2]  to indicate that the target of insertion is the second add element under the appSettings node in configuration file. This results in insertion of the key Settings3 just above the key Setting2.

Adding References to Components

Suppose you decided to place a chart component from Microsoft Chart Controls for Microsoft.NET Framework 3.5 on a user control of a Web Site Factory application created as described at http://www.youtube.com/watch?v=8WLl_p-lM1Y.

If you drag the Chart component from the tool bar and drop it on a user control then five component-specific entries will be created by Visual Studio in the web.config file of your project. Open the configuration file in Visual Studio and search for “chart” to locate every snippet.

The next code generation session will re-create the web.config file and the settings will be lost. Use the following web.config modification instructions to register the chart control in your code generation project.

AppendChild: /configuration/appSettings

<add key="ChartImageHandler" value="storage=file;timeout=20;dir=c:\TempImageFiles\;" />

AppendChild: /configuration/system.web/pages/controls

<add tagPrefix="asp" namespace="System.Web.UI.DataVisualization.Charting" assembly="System.Web.DataVisualization, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />

AppendChild: /configuration/system.web/httpHandlers

<add path="ChartImg.axd" verb="GET,HEAD" type="System.Web.UI.DataVisualization.Charting.ChartHttpHandler, System.Web.DataVisualization, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" validate="false" />

InsertBefore: /configuration/system.webServer/handlers/add[@name='ScriptHandlerFactory']

<remove name="ChartImageHandler" />

AppendChild: /configuration/system.webServer/handlers

<add name="ChartImageHandler" preCondition="integratedMode" verb="GET,HEAD" path="ChartImg.axd" type="System.Web.UI.DataVisualization.Charting.ChartHttpHandler, System.Web.DataVisualization, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />