Blog: Posts from March, 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 March, 2012
Friday, March 30, 2012PrintSubscribe
Virtualization Node Sets Made Easy

The workflow dashboard tutorial explains data controller virtualization.

Implementation of method VirtualizeController creates virtualization node sets to alter the data controller XML definition.

For example, the following snippet sorts the grid view grid1 in descending order of “Required Date” and rearranges its data fields by making “ShippedDate”, “EmployeeID”, and “ShipCity” appear first. The code snippet is written in Visual Basic.

If (IsTagged("OrdersShippedLate")) Then
    ' sort and rearrange 'grid1' by placing ShippedDate, EmployeeID, and ShipCity first
    NodeSet("view[@id='grid1']") _
        .Attr("sortExpression", "RequiredDate desc") _
        .Select("dataField") _
        .Arrange("@fieldName", "ShippedDate", "EmployeeID", "ShipCity")
End If

This is the data view without the virtualization node set:

The data controller view without the virtualization node set

This is the result of the virtualization node set executed at runtime:

Virtualization node set sorts the grid view grid1 in descending order of “Required Date” and rearranges its data fields by making “ShippedDate”, “EmployeeID”, and “ShipCity” appear first

Virtualization node sets alter the in-memory copy of the data controller XML definition. The in-memory copy is discarded as soon as the request from the data view has been processed.

This allows treating the entire application as a large toolkit full of building blocks. Each block may allow a maximum set of capabilities.

Developer uses virtualization node sets when implementing virtualization rules to change the building blocks. The data controller elements can be removed or changed in an arbitrary fashion. For example, the virtualization node set can be executed if a certain use case of the data controller is detected. The user identity may also trigger the virtualization node set execution.

Developers can also elect to add new capabilities to the data controller that were not defined at design time.

The example above uses the method BusinessRules.NodeSet() to create the virtualization node set. Chained calls of Attr(), Select(), and Arrange() methods are altering the data controller XML definition. Each method works on the collection of XML nodes produced by the previous call in the chain.

The basic virtualization node set methods allow selecting, deleting, arranging, and changing attributes and elements of the XML document. Selector expressions written in XPath are used as arguments of the basic methods.

The collection of named plugins is also available. The specially named methods of the virtualization node sets make the node sets much easier to understand. They do not require knowledge or understanding of XPath. Instead the methods are named after the familiar logical elements that developers are modifying in the Project Designer.

The following implementations of method VirtualizeController are written with the use of “plugin” methods instead of the basic ones. Basic methods are shown in the workflow dashboard tutorial. Each virtualization node set starts with the call to method NodeSet() without parameters and continues with calls of “named plugin” methods altering specific areas of the data controller.

C#:

protected override void VirtualizeController(string controllerName)
{
    if (controllerName == "Orders" && IsTagged("OrdersWaitingToShip", "OrdersShippedLate"))
    {
        // make the controller read-only by removing editing actions
        NodeSet().SelectActions("New", "Edit", "Delete", "Duplicate", "Import")
            .Delete();
        // delete all remaining actions in the 'Grid' scope 
        NodeSet().SelectActionGroups("Grid")
            .SelectActions()
            .Delete();
        // add new 'Navigate' action to the 'Grid' scope 
        NodeSet().SelectActionGroups("Grid")
            .CreateAction(
                "Navigate",
                "Orders.aspx?OrderID={OrderID}&_controller=Orders" +
                "&_commandName=Edit&_commandArgument=editForm1");
    }
    if (IsTagged("OrdersWaitingToShip"))
    {
        // sort grid1 and hide the 'ShippedDate' data field
        NodeSet().SelectView("grid1")
            .SetSortExpression("RequiredDate asc")
            .SelectDataField("ShippedDate")
                .Hide();
        // add data field 'ShipCountry' to 'grid1' view
        NodeSet().SelectView("grid1")
            .CreateDataField("ShipCountry");
    }
    if (IsTagged("OrdersShippedLate"))
        // sort and rearrange 'grid1' by placing ShippedDate, EmployeeID, and ShipCity first
        NodeSet().SelectView("grid1")
            .SetSortExpression("RequiredDate desc")
            .ArrangeDataFields("ShippedDate", "EmployeeID", "ShipCity");
}

Visual Basic:

Protected Overrides Sub VirtualizeController(controllerName As String)
    If (controllerName = "Orders" AndAlso IsTagged("OrdersWaitingToShip", "OrdersShippedLate")) Then
        ' make the controller read-only by removing editing actions
        NodeSet().SelectActions("New", "Edit", "Delete", "Duplicate", "Import") _
            .Delete()
        ' delete all remaining actions in the 'Grid' scope 
        NodeSet().SelectActionGroups("Grid") _
            .SelectActions() _
            .Delete()
        ' add new 'Navigate' action to the 'Grid' scope 
        NodeSet().SelectActionGroups("Grid") _
            .CreateAction(
                "Navigate",
                "Orders.aspx?OrderID={OrderID}&_controller=Orders" +
                "&_commandName=Edit&_commandArgument=editForm1")
    End If
    If (IsTagged("OrdersWaitingToShip")) Then
        ' sort grid1 and hide the 'ShippedDate' data field
        NodeSet().SelectView("grid1") _
            .SetSortExpression("RequiredDate asc") _
            .SelectDataField("ShippedDate") _
                .Hide()
        ' add data field 'ShipCountry' to 'grid1' view
        NodeSet().SelectView("grid1") _
            .CreateDataField("ShipCountry")
    End If
    If (IsTagged("OrdersShippedLate")) Then
        ' sort and rearrange 'grid1' by placing ShippedDate, EmployeeID, and ShipCity first
        NodeSet().SelectView("grid1") _
            .SetSortExpression("RequiredDate desc") _
            .ArrangeDataFields("ShippedDate", "EmployeeID", "ShipCity")
    End If
End Sub

This is the effect of the virtualization node sets evaluated at runtime.

Effect of virtualization node sets on the data views

Thursday, March 29, 2012PrintSubscribe
Workflow Dashboard Demo

Fast paced and hectic business days exert a high toll on information workers. Having summary views of the current task items replaces digging and searching through numerous screens in a line-of-business application.

Well constructed summary task views will reflect the actual workflow of the business process. Summary views ensure happy and productive business users. Throw in automatic task view refreshing without any intervention and the level of happiness in application users is likely to increase even more.

Objective

Consider the home page of the Northwind sample. We can greatly improve the life of folks working in the shipping department by replacing the standard site map and login instructions with the summary of orders waiting to ship and orders that were shipped late. Both workflow task views will refresh at predefined intervals.

Standard home page of the Northwind sample created with Code On Time web application generator

This is how the home page of the application may look.

'Summary Task Views' in the Northwind sample reflect the workflow of the shipping deparment

Changing Home Page

Select the project name on the start page of the web application generator and click Design.

Expand the Home node in the Project Explorer and delete the user control instances Home / container1 / control1 and Home / container2 / control2. Right-click each control node and choose Delete option to delete a control instance.

Deleting a user control instance from a page container

Change the properties of Home / container2 as follows and click OK button.

Property Value
Flow New Row
CSS Style Properties margin-top:8px;

Right-click Home / container1 and add a new data view to the container.

Adding a new data view to a page container

Enter the properties of the data view as shown in the table and save changes.

Property Value
Controller Orders
View grid1
Tag OrdersWaitingToShip
Text Orders Waiting to Ship
Page Size 5
Show View Description False
Show View Selector False
Refresh Interval 30

Add another data view to Home / container2. This time the properties of the data view are slightly different.

Property Value
Controller Orders
View grid1
Tag OrdersShippedLate
Text Orders Shipped Late
Page Size 5
Show View Description False
Show View Selector False
Refresh Interval 300

Click OK button to save the properties of the second data view. The Home page node in the Project Explorer will look as follows.

image

Click Browse button to preview the changes.

Modified start page of the Workflow Dashboard Demo with two identical views of 'Orders'

The start page of the application shows two identical data views of Orders. Both views allow changing any orders on screen and show the entire set of orders stored in the database.

Enabling Dedicated Login Page

The home page of the Northwind sample application is not protected. Anonymous users can see the contents of the page. Users are authenticated by entering name and password in the fly-over login window. The login window is activated when users hover over the “Login” link in right-hand corner of the membership bar at the top of the page.

Standard fly-over login window in a Code On Time web application

Perform the following steps to hide the home page from anonymous users.

Exit the Project Designer and click Settings.

Select  Authentication and Membership option in the menu and proceed to Login Window section. Enable a dedicated login page instead of a fly-over login window.

Activating a dedicated login page in Code On Time web application

Click Finish to save the changes.

The application baseline needs to be refreshed. Select Refresh option on the project Summary page.  The Refresh dialog will be displayed with the list of application data controllers.

Project Refresh dialog in Code On Time web application generator

Do not select anything in the list. Simply click the Refresh button at the bottom of the dialog to complete the refresh process.  A dedicated login page will be created next time you re-generate the application.

Enabling Shared Business Rules

We will change the appearance of the Orders on the Home page with the help of data controller virtualization and dynamic access control rules supported in the application framework. This will require writing some code.

For the purpose of this demo we will create a SharesBusinessRules class. Click Settings on the project Summary page and continue to Business Logic Layer. Activate shared business rules and click Finish. You will arrive back to the project Summary page. Proceed to generate the application.

You will be greeted by the dedicated login page when the code generation completes.

Standard dedicated login page in a Code On Time web application

The application framework creates an instance of SharedBusinessRules class whenever you access a page that displays data.  Page data views send requests to your application. Instances of business rules are created to service each and every request.

You will not see any effect of shared business rules at this time - custom business logic has not been implemented yet.

Altering Presentation of Orders on Home Page

First we will change the appearance of orders waiting to ship and orders that were shipped late.

Select the project name on the start page of the application generator and click Develop. The project source code will be displayed in Visual Studio or Visual Web Developer.

Open the file ~/App_Code/Rules/SharedBusinessRules.cs(vb) in the text editor of your development environment.

Replace the default implementation with the following code.

C#:

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

namespace MyCompany.Rules
{
    public partial class SharedBusinessRules : MyCompany.Data.BusinessRules
    {
        public override bool SupportsVirtualization(string controllerName)
        {
            if (controllerName == "Orders" && IsTagged("OrdersWaitingToShip", 
"OrdersShippedLate")) return true; return false; } } }

Visual Basic:

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

Namespace MyCompany.Rules

    Partial Public Class SharedBusinessRules
        Inherits MyCompany.Data.BusinessRules

        Public Overrides Function SupportsVirtualization(controllerName As String) As Boolean
            If controllerName = "Orders" AndAlso IsTagged("OrdersWaitingToShip", 
"OrdersShippedLate") Then Return True End If Return False End Function End Class End Namespace

Our application will detect when Orders data controller is supposed to produce data in response to the requests from the Orders data views located on the Home page. The code verifies the controller name and ensures that the requesting data views are tagged as OrdersWaitingToShip or OrdersShippedLate.  If the method SupportsVirtualization returns true then the application framework will give business rules a chance to modify the definition of the Orders data controller.

We do not want any virtualization changes to go beyond the home page. If users visit the automatically generated Orders page, then no unusual behavior will be seen there.

Now it is time to decide what are we going to change in the presentation of orders on the Home page.

We will:

  • make the controller read-only by removing editing actions;
  • delete all remaining actions in the context menu of the grid view;
  • add new 'Navigate'  action redirecting application user to the “unchanged” Orders page when an order is selected in grid view;
  • hide “ShippedDate” data field in the “orders waiting to ship” view;
  • sort “orders waiting to ship” in ascending order of “RequiredDate”;
  • add “ShipCountry” data field to the “orders waiting to ship”;
  • sort “orders shipped late” in descending order of “RequiredDate”;
  • rearrange “orders shipped late” in such a way that “ShippedDate”, “EmployeeID”, and “ShipCity”  are displayed first.

These sound like a handful!

The snippet of the Orders controller shows the content that must be affected by our modifications.

<?xml version="1.0" encoding="utf-8"?>
<dataController name="Orders" conflictDetection="overwriteChanges" label="Orders" 
                xmlns="urn:schemas-codeontime-com:data-aquarium">
  . . . . .
  <views>
    <view id="grid1" type="Grid" commandId="command1" label="Orders">
      <headerText>$DefaultGridViewDescription</headerText>
      <dataFields>
        <dataField fieldName="CustomerID" aliasFieldName="CustomerCompanyName" />
        <dataField fieldName="EmployeeID" aliasFieldName="EmployeeLastName" />
        <dataField fieldName="OrderDate" columns="10" />
        <dataField fieldName="RequiredDate" columns="10" />
        <dataField fieldName="ShippedDate" columns="10" />
        <dataField fieldName="ShipVia" aliasFieldName="ShipViaCompanyName" />
        <dataField fieldName="Freight" dataFormatString="c" columns="15" />
        <dataField fieldName="ShipName" columns="40" />
        <dataField fieldName="ShipAddress" />
        <dataField fieldName="ShipCity" columns="15" />
      </dataFields>
    </view>
  . . . . .
  <actions>
    <actionGroup id="ag1" scope="Grid">
      <action id="a1" commandName="Select" commandArgument="editForm1" />
      <action id="a2" commandName="Edit" />
      <action id="a3" commandName="Delete" />
      <action id="a6" />
      <action id="a7" commandName="Duplicate" commandArgument="createForm1" />
      <action id="a8" commandName="New" commandArgument="grid1" />
    </actionGroup>
    <actionGroup id="ag2" scope="Form">
      <action id="a1" commandName="Edit" />
      <action id="a2" commandName="Delete" />
      . . . . .
    </actionGroup>
    <actionGroup id="ag3" scope="ActionBar" headerText="New" flat="true">
      <action id="a1" commandName="New" commandArgument="createForm1" cssClass="NewIcon" />
    </actionGroup>
    <actionGroup id="ag4" scope="ActionBar" headerText="Edit/Delete" flat="true">
      <action id="a1" whenKeySelected="true" commandName="Edit" commandArgument="editForm1" 
              cssClass="EditIcon" whenView="grid1" />
      <action id="a2" whenKeySelected="true" commandName="Delete" 
              cssClass="DeleteIcon" whenView="grid1" />
    </actionGroup>
    <actionGroup id="ag5" scope="ActionBar" headerText="Actions">
      . . . . .
      <action id="a6" commandName="Import" commandArgument="createForm1" />
    </actionGroup>
  </actions>
</dataController>

Making changes to the data controller in a text editor would not be difficult. One could copy, rename, move, and change various portions of the file to accomplish the desired result.

We don’t want to change the static definition of the data controller.
Multiple versions of the same controller are not welcomed either  -
this would become a maintenance nightmare.

Data Controller Virtualization comes to the rescue. It allows conditional modification of the data controller at runtime. Developer becomes a true magician and dynamically alters the actual definition of the controller based on a given use case.

Add the following implementation of the method VirtualizeController to the SharedBusinesRules class. The implementation takes advantage of the method BusinessRules.NodeSet() and molds the data controller definition at runtime according to the specification suggested above.

C#:

protected override void VirtualizeController(string controllerName)
{
    if (controllerName == "Orders" && IsTagged("OrdersWaitingToShip", "OrdersShippedLate"))
    {
        // make the controller read-only by removing editing actions
        NodeSet("action[@commandName = $name]",
            "New", "Edit", "Delete", "Duplicate", "Import").Delete();
        // delete all remaining actions in the 'Grid' scope 
        NodeSet("actionGroup[@scope='Grid']")
            .Select("action").Delete();
        // add new 'Navigate' action to the 'Grid' scope 
        NodeSet("<action>")
                .Attr("commandName", "Navigate")
                .Attr("commandArgument",
                        "Orders.aspx?OrderID={OrderID}&_controller=Orders" +
                        "&_commandName=Edit&_commandArgument=editForm1")
                .AppendTo("c:actionGroup[@scope='Grid']");
    }
    if (IsTagged("OrdersWaitingToShip"))
    {
        // sort 'grid1' and hide the 'ShippedDate' data field
        NodeSet("view[@id='grid1']")
            .Attr("sortExpression", "RequiredDate asc")
            .Select("dataField[@fieldName='ShippedDate']")
            .Attr("hidden", "true");
        // add data field 'ShipCountry' to 'grid1' view
        NodeSet("<dataField>").Attr("fieldName", "ShipCountry")
            .AppendTo("view[@id='grid1']/dataFields");
    }
    if (IsTagged("OrdersShippedLate"))
        // sort and rearrange 'grid1' by placing ShippedDate, EmployeeID, and ShipCity first
        NodeSet("view[@id='grid1']")
            .Attr("sortExpression", "RequiredDate desc")
            .Select("dataField")
            .Arrange("@fieldName", "ShippedDate", "EmployeeID", "ShipCity");
}

Visual Basic:

Protected Overrides Sub VirtualizeController(controllerName As String)
    If (controllerName = "Orders" AndAlso IsTagged("OrdersWaitingToShip", "OrdersShippedLate")) Then
        ' make the controller read-only by removing editing actions
        NodeSet("action[@commandName = $name]",
            "New", "Edit", "Delete", "Duplicate", "Import").Delete()
        ' delete all remaining actions in the 'Grid' scope 
        NodeSet("actionGroup[@scope='Grid']") _
            .Select("action").Delete()
        ' add new 'Navigate' action to the 'Grid' scope 
        NodeSet("<action>") _
            .Attr("commandName", "Navigate") _
            .Attr("commandArgument",
                "Orders.aspx?OrderID={OrderID}&_controller=Orders" +
                "&_commandName=Edit&_commandArgument=editForm1") _
            .AppendTo("c:actionGroup[@scope='Grid']")
    End If
    If (IsTagged("OrdersWaitingToShip")) Then
        ' sort grid1 and hide the 'ShippedDate' data field
        NodeSet("view[@id='grid1']") _
            .Attr("sortExpression", "RequiredDate asc") _
            .Select("dataField[@fieldName='ShippedDate']") _
            .Attr("hidden", "true")
        ' add data field 'ShipCountry' to 'grid1' view
        NodeSet("<dataField>").Attr("fieldName", "ShipCountry") _
            .AppendTo("view[@id='grid1']/dataFields")
    End If
    If (IsTagged("OrdersShippedLate")) Then
        ' sort and rearrange 'grid1' by placing ShippedDate, EmployeeID, and ShipCity first
        NodeSet("view[@id='grid1']") _
            .Attr("sortExpression", "RequiredDate desc") _
            .Select("dataField") _
            .Arrange("@fieldName", "ShippedDate", "EmployeeID", "ShipCity")
    End If
End Sub

The code only executes when the data is requested from the home page by the views tagged as OrdersWaitingToShip and OrdersShippedLate. Go ahead and take a look at the effect of modifications in the web browser.

Presenting Orders Waiting To Ship or Shipped Late

We need to filter both home page data views to show a specific subset of orders reflecting the view’s purpose. The following implementation of method EnumerateDynamicAccessControlRules will do the job.

C#:

protected override void EnumerateDynamicAccessControlRules(string controllerName)
{
    if (IsTagged("OrdersWaitingToShip"))
        RegisterAccessControlRule("OrderID",
            "[ShippedDate] is null",
            AccessPermission.Allow);
    if (IsTagged("OrdersShippedLate"))
        RegisterAccessControlRule("OrderID",
            "[ShippedDate] is not null and [RequiredDate] < [ShippedDate]",
            AccessPermission.Allow);
}

Visual Basic:

Protected Overrides Sub EnumerateDynamicAccessControlRules(controllerName As String)
    If (IsTagged("OrdersWaitingToShip")) Then
        RegisterAccessControlRule("OrderID",
            "[ShippedDate] is null",
            AccessPermission.Allow)
    End If
    If (IsTagged("OrdersShippedLate")) Then
        RegisterAccessControlRule("OrderID",
            "[ShippedDate] is not null and [RequiredDate] < [ShippedDate]",
            AccessPermission.Allow)
    End If
End Sub

The data view tagged as OrdersWaitingToShip will show the orders with the empty “ShippedDate”.

The data view tagged with OrdersShippedLate will show the orders that were shipped but the required date is less than the shipped date.

Analyzing Dashboard Capabilities

Here is the dashboard reflecting the business workflow of the shipping department at our fictitious mail order company Northwind.

Completed 'Workflow Dashboard' with 'Summary Task Views' in the Northwind sample reflecting the business workflow of the shipping deparment

Users are not able to change data in the views. The row context menu is not displayed when users move the mouse pointer over the links in the first column. Action bar does not display New Orders and Import actions.

Columns in the grid views are rearranged.

The top view is sorted in ascending order of “Required Date”. Column “Shipped Date” is not displayed.

The bottom view is sorted in descending order of “Required Date”. The first columns are “Shipped Date”, “Employee ID” (aliased with “Employee Last Name”), and “Ship City”.

The top view is automatically refreshed every 30 seconds. The bottom one is refreshed every 5 minutes. The refreshing happens if user is not interacting with the views longer than their respective refresh intervals.

If a user clicks on any link in the first column of either grid view then the web browser will navigate to the Orders page. The page will open with the selected order presented in edit mode.

'Orders' page displayed when a user selects an order on the dashboard

Users can edit or add  new Order Details while remaining on the same Orders page.

Users will be transferred back to the home page as soon they click on OK or Cancel buttons in the Orders form.

Notice that the automatically generated Orders page is not affected by virtualization rules. Navigate to the Orders page by selecting Customers / Orders menu option and you will see the default layout of the grid view and data editing  commands unchanged.

URL Hashing

Look close at the URL in the address bar of the browser when user navigates to the Orders page. You will see something like this:

Data controller URL parameters displayed in the web browser address bar.

You can easily spot the OrderID and data controller URL parameters activating the edit mode of the order form.

Sometimes you do not wish to reveal this information.

Select the project name on the start page of the application generator and click Settings. Continues to Features and activate EASE Configuration. Enable the URL Hashing option.

Enabling URL Hashing in the project created with Code On Time web application generator

Click Finish button and generate the app. Select any order and observer that the URL is not as revealing as previously.

Data controller URL parameters are 'hidden' if URL Hashing is enabled in a Code On Time web application

Any attempts to alter the URL will result in Access Denied message. Learn about URL Hashing.

Conclusion

Data Controller Virtualization enables rapid development of complex workflow dashboards. Developers can treat the core application data controllers as a collection of building blocks. Developers can  alter the definition of data controllers based on arbitrary conditions such as user identity or use case of the data controller as was explained above.

Virtualization plugins allows rapid development of virtualization rules by eliminating the need to use XML elements in the node sets.

Tuesday, March 27, 2012PrintSubscribe
Creating an SQL Azure Database

Log in to your Windows Azure Platform at https://windows.azure.com/ and clicking on Portal. At the bottom, press New and select Data Services | SQL Database | Quick Create. Specify a name of “HR” and login credentials for the database. Press Create SQL Database.

Creating a new SQL Database.

When the database is created, click on the name in the list of all items, and then press Manage on the bottom toolbar.

Managing the database.

Accept the prompt to add a firewall exception. A new tab will open the management screen. Enter your user credentials and press Log on.

You will be taken to a summary screen that shows database statistics.

Administration page of Microsoft SQL Azure database management web app

Click on the Design button in the bottom left corner. This will take you to a list of all tables in the database. As this database has just been created, the list of tables will be currently empty. Let’s add a table by pressing the New table button.

New Table button in Microsoft SQL Azure database management web app

Add the following fields, starting with the Column name and then selecting type:

Column Select type Is Identity? Is Required?
JobID int Yes Yes
Title nvarchar(50)    
Description ntext    

Jobs table created in HR database using SQL Azure database management web app

In the Table Name field above the columns, enter “Jobs”. Save the table by pressing Save on the ribbon at the top.

Click on Design again. Create another table, name it “Employees”, and set up the following field information:

Column Select type Is Identity? Is Required?
EmployeeID int Yes Yes
LastName nvarchar(30)   Yes
FirstName nvarchar(50)   Yes
JobID int    
Salary money    
Notes ntext    
Photo image    
HireDate datetime    

Employees table created in HR database using SQL Azure database management web app

Save the table. Let’s add a foreign key reference for the JobID field between Employees and Jobs. Above the list of columns, click on Indexes and Keys.

Click on the Add a foreign key relationship header on the right side. Check the JobID field, choose the table dbo.Jobs, and select column JobID.

Foreign key relationship between Jobs and Employees table created in HR database using SQL Azure database management web app

Press Save to save the foreign key.

Now it’s time to create a web application from the database and deploy this application to the cloud. For detailed instructions on Azure Factory project creation and deployment, please refer to this article.

Run Code On Time generator and create a new Azure Factory project. Give this project a name, and specify the connection string of the database using the Fully Qualified DNS Name of the server. Enable ASP.NET Membership and Session State Management. Use the Grapello theme. Generate the application, and you will have a full featured web application running locally on your computer and connecting to your SQL Azure database.

To publish, go back to the web application generator, click on the project name, and press Publish. A Windows Explorer window will open with two files necessary for deployment. Go back to the Windows Azure Platform, and open Hosted Services folder. Create a new Hosted Service, and specify the settings. The package and configuration file are in the opened Explorer window. Press OK to create the deployment. It may take a while for the service to start.

Once complete, you will be able to access the website using the link under Properties of the deployment. Click on this link, and you will be taken to the fully functional website. 

Code On Time Azure Factory web application running in Azure staging deployment

If you look at the URL, you will notice that it uses the ID of the deployment, not the requested DNS Name. This is because the deployment is a staging deployment. You can go back to the management portal, and choose to Swap to change it into a production deployment. This will use the URL you specified during creation of the hosted service.

Code On Time Azure Factory web application running in Azure production deployment