RapidWebDev UI Framework Instruction

UI Framework is to develop standard AJAX web forms by xml configuration, interfaces' implementation and ASCX templates. There are 6 significant advantages of this framework.
  1. the request and response data are both very small by asynchronous connection in JSON between client and server in the developed web forms.
  2. easy to consolidate style, layout and behaviors of all web forms in a system by implementing some layout interfaces that the web forms are rendered by xml configuration.
  3. engineers don't need to write any code to control UI display workflow which has been fully controlled by the framework.
  4. easy to write unit test cases for UI implementation which is decoupling to xml configuration and ASCX templates.
  5. the independent UI implementation is easy to be extended and reused in different scenarios.
  6. web form controls/user interactions are integrated with permission.

The chapters of this article are,

1. Basis & Concept

Rapid web is used to develop pure AJAX driven web forms by xml without writing much ASP.NET web form code, HTML, CSS and JS. The following screenshot is a web form created in RapidWeb. We name it as “dynamic page”.



A dynamic page is composed of query panel, button panel, grid panel, detail panel and aggregate panel at most. Detail and aggregate panel are hidden but shown in a popup window when user CRUD a new entry or process actions against entries. The screen shot shows the user is creating a new entry in detail panel.


  • Detail panel is used to create, update and view a single entry.
  • Aggregate panel is used to process actions against multiple entries selected in grid, like bulk approve, bulk delete etc.
  • Button panel is used to configure buttons for custom actions.
In a dynamic page, only grid panel is required and only button panel can be multiple configured. And rendering sequence of query panel, button panels and grid panel depends on the xml configuration.

2. Development

When you develop a dynamic page, you may need to
  • Xml configuration to dynamic page surface with Query, Grid and Button panels.
  • Implement IDynamicPage to query and single delete.
  • Implement IDetailPanel to create, update and view a single entry.
  • Implement IAggregatePanel to process actions to multiple selected entries in grid.
  • Create an ASCX template without CS rendered in detail panel.
  • Create an ASCX template without CS rendered in aggregate panel.
You don’t need to write all things above for every dynamic page. That depends on the requirement of the web form. And there are three abstract classes implement IDynamicPage, IDetailPanel and IAggregatePanel with some fundamental staff done. So you don’t need to start implementation from interfaces for most cases.

So many staff we need for a web form. How you can advertise that the infrastructure saves up to 60% works in web form based application?

We’re sure it’s true. The article compares Rapid Web Development and traditional method below in detail step by step and introduces how to complete your first dynamic page. In the following sections, the article introduces Query, Grid, Button, Detail and Aggregate panels one by one.

2.1. Dynamic Page Overview

A dynamic page is composed of Query, Grid, Button Panels, Detail Panel and Aggregate Panel as following code snippet. The dynamic page should have an IDynamicPage implementation class and a unique object Id. Permission value refers to authorization for accessing users. The article introduces permission in later chapters.

<Page xmlns="http://www.baojiansoft.com/schemas/dynamicpage" ObjectId="OrganizationManagement" Type="BaoJianSoft.Platform.Web.DynamicPage.OrganizationManagement, BaoJianSoft.Platform">
	<Title>Page Title</Title>
	<PermissionValue>OrganizationManagement</PermissionValue>
	<Panels>
		<!-- Query, Grid, Button Panels, Detail Panel and Aggregate Panel here -->
	</Panels>
</Page>

2.1.1. SetupContextTempVariables

The method SetupContextTempVariabes exists in all IDynamicPage, IDetailPanel and IAggregatePanel. It’s used to setup temporary variables to format variables configured in xml configuration.

Almost attributes and elements in dynamic page xml configuration support variable markup as “$VariableName$” seeing the following code snippet as an example. Developer can setup temporary variable “OrganizationType” in SetupContextTempVariables so that RapidWebDev will replace them in xml configuration with the values at runtime.

<Page xmlns="http://www.baojiansoft.com/schemas/dynamicpage" ObjectId="OrganizationManagement" Type="BaoJianSoft.Platform.Web.DynamicPage.OrganizationManagement, BaoJianSoft.Platform">
	<Title>$OrganizationType$ Organization Management</Title>
	<PermissionValue>$OrganizationType$.OrganizationManagement</PermissionValue>
	<Panels>
		<!-- Query, Grid, Button Panels, Detail Panel and Aggregate Panel here -->
	</Panels>
</Page>

If we setup OrganizationType to XXX as following C# code, Title and PermissionValue of above xml configuration will be replaced to the following xml code snippet.

public override void SetupContextTempVariables(object sender, SetupApplicationContextVariablesEventArgs e) 
{
	e.TempVariables["OrganizationType"] = "XXX";
}

<Page xmlns="http://www.baojiansoft.com/schemas/dynamicpage" ObjectId="OrganizationManagement" Type="BaoJianSoft.Platform.Web.DynamicPage.OrganizationManagement, BaoJianSoft.Platform">
	<Title>XXX Organization Management</Title>
	<PermissionValue>XXX.OrganizationManagement</PermissionValue>
	<Panels>
		<!-- Query, Grid, Button Panels, Detail Panel and Aggregate Panel here -->
	</Panels>
</Page>

2.1.2. Event Sequence


2.2. Query Panel

Take above screenshot as the example on managing “Inc” (Internal Cooperation). We should configure QueryPanel xml element first and implement the method Query of interface IDynamicPage as following code snippet.

<QueryPanel HeaderText="Query Inc">
	<TextBox FieldName="OrganizationCode" Label="Code: " />
	<TextBox FieldName="OrganizationName" Label="Name: " />
	<ComboBox FieldName="OrganizationTypeId" Editable="false" FieldValueType="System.Guid" ForceSelection="true" Label="Type: ">
		<DynamicDataSource Root="Records" TextField="Name" ValueField="OrganizationTypeId" Url="/Services/OrganizationService.svc/json/FindOrganizationTypes/Inc" />
	</ComboBox>
	<CheckBoxGroup FieldName="Status" Label="Status: " FieldValueType="BaoJianSoft.Platform.OrganizationStatus, BaoJianSoft.Platform">
		<Item Checked="true" Text="Enabled" Value="Enabled" />
		<Item Text="Pending" Value="Pending" />
		<Item Text="Disabled" Value="Disabled" />
	</CheckBoxGroup>
</QueryPanel>

public QueryResults Query(QueryParameter parameter)
{
	using (MembershipDataContext ctx = DataContextFactory.Create<MembershipDataContext>())
	{
		IQueryable<Organization> query = ctx.Organizations;
		QueryPredicate queryPredicate = parameter.Expressions.Compile();
		query = query.Where(queryPredicate.Predicate, queryPredicate.Parameters);

		string sortExpression = null;
		if (parameter.SortExpression != null)
			sortExpression = parameter.SortExpression.Compile();
		if (Kit.IsEmpty(sortExpression))
			sortExpression = "LastUpdatedDate DESC";
		query = query.OrderBy(sortExpression);

		int recordCount = query.Count();
		var queryResults = query.Skip(parameter.PageIndex * parameter.PageSize).Take(parameter.PageSize);
		return new QueryResults(recordCount, queryResults);
	}
}

The RapidWeb framework renders to UI with 2 textboxes, 1 combo box and 1 checkbox group as Picture-1 by xml code snippet. We don’t explain xml schema in detail here. When you write xml in Visual Studio with setup schema correctly, you can get detail information from IntelliSense of Visual Studio.

When user clicks “query” button in UI, the method Query of IDynamicPage will be invoked automatically. The framework assembles query and sort expression intelligently to QueryParameter which includes QueryParameterExpressionCollection, SortExpression, PageSize and PageIndex. You can compile QueryParameterExpressionCollection to Linq expression tree and integrate with your query expression. SortExpression does in the same way. The returned QueryResults will be bound to grid automatically.

In Rapid Web Development, you don’t need to write ASP.NET controls or parse HTTP GET/POST manually. And you don’t need to check each control/GET/POST item and assemble it into query expression if it has a valid value. These are completed by the framework yet. The 10 lines code helps you finishing query with sorting and paging without touching UI controls. And the method becomes much easier to write test cases in this way.

2.3. Grid Panel

Take above screenshot as the example on managing “Inc” (Internal Cooperation).

<GridViewPanel HeaderText="Query results"
	EntityName="Inc"
	EnabledCheckBoxField="true"
	PageSize="25"
	PrimaryKeyFieldName="OrganizationId"
	DefaultSortField="OrganizationName"
	DefaultSortDirection="ASC">
	<ViewButton />
	<EditButton />
	<DeleteButton />
	<Fields>
		<Field FieldName="OrganizationCode" HeaderText="Code" Width="80" />
		<Field FieldName="OrganizationName" HeaderText="Name" Width="120" />
		<Field FieldName="OrganizationType.Name" HeaderText="Type" Width="120" />
		<Field FieldName="Properties[&quot;Contact&quot;]" HeaderText="Contact" Align="Center" Sortable="false" Hidden="true" />
		<Field FieldName="Properties[&quot;PhoneNo&quot;]" HeaderText=" PhoneNo " Align="Center" Sortable="false" Hidden="true" />
		<Field FieldName="Status" HeaderText=" Status " Width="60">
			<Transform-Switch>
				<Case Value="Enabled">&lt;span style='color:green'&gt;Enabled&lt;/span&gt;</Case>
				<Case Value="Pending"> Pending </Case>
				<Case Value="Disabled">&lt;span style='color:red'&gt; Disabled &lt;/span&gt;</Case>
			</Transform-Switch>
		</Field>
		<Field FieldName="LastUpdatedBy" HeaderText=" ModifiedBy" Align="Center" Hidden="true">
			<Transform-Callback Type="BaoJianSoft.Platform.Web.DynamicPage.GridViewFieldValueTransformCallback.ShowUserDisplayName, BaoJianSoft.Platform"/>
		</Field>
		<Field FieldName="LastUpdatedDate" HeaderText=" ModifiedOn" Align="Center" Width="150" />
		<RowView FieldName="Description" />
	</Fields>
</GridViewPanel>

Grid only supports 3 kinds of inline button in each row, View, Edit and Delete. For detail of xml elements and attributes please refer to DynamicPage.xsd. And when you configure it in Visual Studio, you will get help from IntelliSense if you installed schema correctly.

2.3.1. Paging & Sorting

When user sorts and paginates in grid, the method Query of IDynamicPage will be invoked and push new data into grid as we introduced in “Query Panel” chapter. So you don’t have any works to do on sorting and paging.

2.3.2. View & Edit

When user intends to view/edit an entry in a row, ASCX template for detail panel and interface IDetailPanel will be used. The method LoadReadOnlyEntity(string entityId) is invoked for View and LoadWritableEntity(string entityId) for Edit. In these two methods, you need to convert string typed entity ID to correct type and load the entity by ID. Then set the entity to controls inner of detail panel ASCX template. The article will introduce more about detail panel in the following chapters. So you don’t need to work on popup a window or show a panel for View & Edit. The UI display logic is taken by the framework yet.

2.3.3. Delete

When user clicks delete button in a row of grid, the method Delete of IDynamicPage will be invoked with deleting entity ID. Developers only need to focus on how to delete an entry by ID.

2.3.4. Field Data Bound

A grid panel is composed of multiple fields and zero/one row view segment. FieldName of configured Field or Row View should be an existed property of entities returned from method Query of IDynamicPage. The configuration supports to configure a transformer to convert field value before rendering to UI seeing detail in DynamicPage.xsd.

2.3.5. Visibility of Checkbox, View, Edit and Delete button

Once we configured checkbox, view, edit or delete button, they will be rendered onto UI by default for every row. But we have the requirement to display checkbox, view, edit or delete button depends on the data, like it should not display delete button for recycled data. In this case, we can implement “void OnGridRowControlsBind(GridRowControlBindEventArgs e)” of IDynamicPage. The method will be invoked for each row. You can get the binding data item from GridRowControlBindEventArgs and set visibility of checkbox, view, edit or delete button there.

2.4. Detail Panel

The developers need to write ASCX template to the area with red background color seeing Picture-3. When you take a look at body of the popup window, the area with white background color is a standalone web page in an IFrame. The web page is dynamically rendered by detail panel xml configuration.



A sample code snippet for detail panel is as following,

<DetailPanel HeaderText="Organization Profile" ShowMessageAfterSavedSuccessfully="false">
	<Type>BaoJianSoft.Platform.Web.DynamicPage.OrganizationDetailPanel, BaoJianSoft.Platform</Type>
	<SkinPath>~/Templates/Platform/Organization.ascx</SkinPath>
	<SaveAndAddAnotherButton />
	<SaveAndCloseButton />
	<CancelButton />
</DetailPanel>

The “Type” xml element above is to configure a detail panel implementation for business logics. The interface IDetailPanel has following main methods,
  • Create
  • Update
  • Reset
  • LoadWritableEntity
  • LoadReadOnlyEntity
  • OnInit
  • OnLoad
  • OnPreRender
  • SetupContextTempVariables
Detail panel works only in three status as create, update and view. “Create” is to render a blank form to add a new entity. “Update” is to load an existed entity by ID and save the entity with new values. “View” is to load an existed entity by ID for view only. In the following chapters, the article introduces these three actions in detail.

OnInit, OnLoad and OnPreRender are similar to the methods in ASP.NET Page. They are the methods for developers to interact with controls in different rendering phrases.

2.4.1. Page URL

A sample URL for the web page rendering detail panel to add a new entity as below,

/OrganizationManagement/DetailPanel.svc?entityid=null&rendermode=New&ObjectId=OrganizationManagement&Domain=Inc

Detail panel is a standalone web page wrapping the custom template. When you take a look at the sample URL, you can find interesting query parameters as EntityId, RenderMode and ObjectId.
  • ObjectId indicates which dynamic page will be rendered. It’s mapped to ObjectId of dynamic page xml configuration.
  • RenderMode supports three values as View, Update and New. It indicates which status of detail panel for current access.
  • EntityId is needed only for View and Update which indicates what entity is loaded. In New render mode, it should be null or not specified.

This design makes the developed web form reusable. Take an example, you created a dynamic page for users to create orders. When you need to show order detail information for users somewhere else, you can use the same detail panel by URL with EntityId, RenderMode equals to View and correct ObjectId. And you don’t need to worry about the security because the infrastructure has helped on that already.

We have rich successful experience that we created a single powerful detail panel template and abstract an entity detail panel class inherited from DetailPanel for common functionalities. Then we implement very small child classes to control template controls and workflow for different business scenario.

2.4.2. Event Sequence



You can get controls marked with Binding attribute after the step “Resolve Controls From Template”.

2.4.3. Template Controls

In detail panel development, developers need to resolve references to controls in custom template using attribute markup. With following declaration, Rapid infrastructure will resolve the TextBox control with ID equals to “TextBoxOrganizationCode” in template and set it to this class member. Then developers access web controls in IDetailPanel implementation class in this way.

[Binding]
protected TextBox TextBoxOrganizationCode;

2.4.4. Create

In Create mode, there are 3 buttons below the custom template seeing in Picture-3. They’re “Save & Close”, “Save & Add Another” and “Cancel”. When the detail panel page loaded, the above 5 methods are not invoked at all but your custom ASCX template will be loaded into the detail panel web page.

When user clicks button “Save & Close” or “Save & Add Another” in UI, the method Create will be invoked. Developers should write code to get values from controls and save them here and return ID of the new entity as string out.

The method Reset will be invoked after Create if user clicks button “Save & Add Another”. It’s used to reset form controls to default state then the user can add another new entity continuously. But you don’t need to work on Reset if the class starts from abstract DetailPanel instead of implementing interface IDetailPanel directly.

2.4.5. Update

Update is to load an existed entity into UI by “LoadWritableEntity”. Then save new values from UI submit by “Update”.

2.4.6. View

View is to load an existed entity into UI in read only mode by “LoadReadOnlyEntity”. You don’t need to work on setting controls into read only but only implementing “LoadWritableEntity” to set values to controls if the detail panel inherits from abstract DetailPanel. The abstract DetailPanel intelligently switches the controls into read only.

2.5. Button Panel

Take a look at Picture-1 in this article. Button panel is used to configure multiple buttons in for custom actions. The sample code to configure 2 buttons “Add” and “Submit” as following code snippet.

<ButtonPanel ButtonAlignment="Left">
	<Button CommandArgument="New" Type="NewImage" ToolTip="Add a new product" />
	<Button CommandArgument="Submit" Type="CustomImage" ImageUrl="~/resources/images/shared/icons/fam/application_go.png" ToolTip="Submit all products">
		<GridSelectionRequired WarningMessage="Please select products in grid before submit." />
	</Button>
</ButtonPanel>

We see there has the attribute CommandArgument for each button. It’s used for developers to integrate .NET managed code with configured UI by interface IAggregatePanel. The main method Save of that interface has two arguments, “command argument” and “entityIdEnumerable”.

When a user clicks a button in button panel, the method Save will be invoked with corresponding command argument of that configured button and entity identities of selected entities in grid. Developer should implement business logics through this method in aggregate panel seeing more detail in the chapter “Aggregate Panel”.

There are some exceptions for Command Argument of buttons.
  • "Delete", "Update" and "View" are protected which cannot be configured as command argument. They have been used by grid view.
  • "New" is used to integrate with detail panel but not aggregate panel for adding a new entity. When a user clicks the button with “New”, the detail panel will be shown up with blank form. Please see detail description in chapter “Create” of “Detail panel”.
  • “Print” and “DownloadExcel” are default command arguments. When a user clicks the button with “Print”, there will show a popup window to print all records in grid includes the ones not in current pagination. When a user clicks the button with “DownloadExcel”, there will pop up a excel document to download for all records in grid includes the ones not in current pagination as well. Developer doesn’t need to write any code for these two command arguments actually.

The exceptional command arguments listed above are well documented in DynamicPage.xsd. They may get modified in future version of RapidWebDev solution. We will keep comments and documentation in DynamicPage.xsd up to date.

2.6. Aggregate Panel

Aggregate panel is used for bulk actions against multiple records in grid basically. A sample aggregate panel xml configuration is as following code snippet.

<AggregatePanel HeaderText="Submit Products" ShowMessageAfterSavedSuccessfully="false">
	<Type>SLUCCMS.Web.Workflow.SubmitUncertificatedOrgAggregatePanel, SLUCCMS</Type>
	<SkinPath>~/Sluccms/DynamicPage/Workflow/SubmitUncertificatedOrg.ascx</SkinPath>
	<SaveButton />
	<CancelButton />
</AggregatePanel>

The “Type” xml element above is to configure an aggregate panel implementation for business logics. The interface IAggregatePanel has following main methods,
  • Save
  • SetupContextTempVariables
  • OnInit
  • OnLoad
  • OnPreRender

2.6.1. Event Sequence


2.6.2. Template Controls

In aggregate panel development, developers need to resolve references to controls in custom template using attribute markup as detail panel. The template used in aggregate panel is to customize UI to user input for bulk actions. Take an example, when user bulk approves orders in aggregate panel, the system needs input likes approval decision and comment besides the target orders.

2.6.3. UI View

There only allows maximum one aggregate panel in a dynamic page. If you have requirement that needs multiple actions supported in a page and each action needs different view to others, you should have ASCX template with panels supporting all command arguments. Then manually write code to switch visibility of panels in OnLoad depends on the command argument.

2.7. Exception Handling

If you want to show error/warning messages to users in dynamic page, detail panel and aggregate panel, you can throw ValidationException in the code directly. The exception is caught by RapidWebDev as a known exception that the message of it will be shown onto UI for users.

RapidWebDev also tries to catch generic exceptions. The generic exception will be logged and shown as an internal server error to users.

3. Permission

Dynamic page xml configuration allows developer to configure permission value which integrates to authorization. The configured permission value is only the root permission for the dynamic page.

Take an example. We configure “UserManagement” in a dynamic page xml configuration, actually all “UserManagement “, “UserManagement.All”, “UserManagement.New”, “UserManagement.Update”, “UserManagement.Delete”, “UserManagement.View” and “UserManagement.CommandArgument” will be used.
  • “UserManagement” – the user only can access the Query-Grid page but cannot do Update, Add, Delete and any other bulk action.
  • “UserManagement.All” – the user is authorized to do any actions in the dynamic page. “XXX.All” means the user owns all permission values start with “XXX.” or “XXX”.
  • “UserManagement.New” – the user can create a new entry in the page.
  • “UserManagement.Update” – the user can update an entry in the page.
  • “UserManagement.Delete” – the user can delete an entry in the page.
  • “UserManagement.View” – the user can see a particular entry in detail panel of dynamic page but not authorized to query and list.
  • “UserManagement.CommandArgument” – the user can see the button with command argument in button panel and do the action in aggregate panel.

So that when you develop a dynamic page, you can configure and develop all possible actions at a time and don’t worry about the permission. The authorization has been managed by RapidWebDev infrastructure already.

Exceptionally, configure “EveryOne” to permission value so that every authenticated user can do any actions in the page. And configure “Anonymous” so that every system user included unauthenticated can do any actions in the page. We suggest that not create a dynamic page with modification for the permission “EveryOne” or “Anonymous”. That’s dangerous!

Last edited Feb 6, 2010 at 3:20 PM by eungeliu, version 8

Comments

No comments yet.