BLD Technology Overview

Peter’s Business Logic Driven UI (“BLD”) allows separating the User Interface Layer (“UI”) from Business Logic Layer (“BLL”) and the rest of the layers in a business application.

Multilayered design

It provides classes for both the User Inteface Layer and Business Logic Layer. In fact, it can substantially define both layers. Its tools for the User Interface Layer are built around ASP.NET Web Forms v4 and higher. Its Business Logic Layer classes can be used in any User Interface Layer, so long as the Microsoft .net framework is installed.

There are a massive number of classes for each layer, to allow a wide variety of usages. In addition, this is a carefully crafted API intended to allow expansion and in many cases, replacement of the original classes with the goal that the developer should not run into any API limitations they can’t work around. (It’s not acceptable to be building an application on top of an API and hitting a wall after months of work.)

Building the Business Logic Layer

There are two major elements of the Business Logic Layer and BLD provides a rich set of tools for both. They are:

  • Business rules – Classically this involves validation rules, whether on individual columns of your table, or at the table level itself. However, there are an enormous number of non-validation rules: Security restrictions, default values, lists of legal values (that can be shown in a dropdownlist for example), column dependencies (where the value of one column impacts how another column is used or validated), etc.
  • Data Access Objects – Classes that handle the CRUD (“Create, read, update, delete”) actions. The Data Access Layer does the real work of communicating with your database, but it doesn’t know how to handle special cases for each table. If you want to develop methods that query the database in different ways, those methods go into the Data Access Objects, as does methods that insert, update, and delete records. These methods call upon the Data Access Layer’s tools to get the job done.

Business rules using DataAnnotation attributes

Microsoft developed the following approach for creating business rules: Add attribute objects declared in the System.ComponentModel.DataAnnotations namespace to properties of each Entity class.

Understanding the Entity class

The Entity class is a significant part of this multilayered design. It represents a single table or view in your database, where its properties represent columns. BLD calls those properties “DataFields”.

There are actually two versions of the Entity class. The Data Access Layer defines it to mimic the actual table. You will create the second version in the Business Logic Layer to host your business rules. After all, your business rules don’t belong in the Data Access Layer. These two class definitions are actually merged together because they have the same class name and namespace, plus use the partial keyword. So consumers of the Entity class only see a single class, with all elements from both Data Access Layer and Business Logic Layer combined.

Defining business rules as attribute objects

You can define any rule you can imagine, just by subclassing System.Attribute. Most rules have properties to customize them. Only a few have support methods. The idea is that while they may describe a rule, they don’t always implement code for that rule. That’s often left to the consumer of the business rule, which can be either the Data Access Object, Entity class, or the User Interface Layer.

Validation attributes do have a support method. Their Validate() method is passed the value to be validated and is expected to throw an exception reporting an error. You Data Access Object will use this to enforce validation before asking the Data Access Layer to Update or Insert a record.

The System.ComponentModel.DataAnnotations namespace provides relatively few business rules, and those included are not usually rich enough to support some real world cases. (For example, Validation attributes cannot be disabled based on a dependency with another column.) BLD resolves this with its PeterBlum.DES.DataAnnotations namespace, loaded with business rules. You can also create your own.

Here is an example Entity class defined with DataAnnotation attributes.

[C#]
using DESDA=PeterBlum.DES.DataAnnotations;
… 
[MetadataType(typeof(CategoryMetadata))]
[EntityDAOType(typeof(CategoryEntityDAO))]
public partial class Category  
{
 // business logic methods go here.
}

[DESDA.DisplayName("Categories")]
public class CategoryMetadata
{
  [DESDA.Required()]
  [DESDA.DisplayName("Name")]
  public object CategoryName { get; set; }

  [DESDA.DataType(DataType.MultilineText)]
  [DESDA.StringLength(2000)]
  public object Description { get; set; }
}
[VB]
Imports DESDA=PeterBlum.DES.DataAnnotations
…
<MetadataType(GetType(CategoryMetadata))> _
<EntityDAOType(GetType(CategoryEntityDAO))> _
Public Partial Class Category
' business logic methods go here.
End Class

<DESDA.DisplayName("Categories")> _
Public Class CategoryMetadata

  <DESDA.Required()> _
  <DESDA.DisplayName("Name")> _
  Public Property CategoryName As Object
  ...
  End Property

  <DESDA.DataType(DataType.MultilineText)> _
  <DESDA.StringLength(2000)>_
  Public Property Description As Object
  ...
  End Property
End Class

You can see the actual Entity class for the BLL defined as “Category”, plus another class, “CategoryMetadata”, which hosts the DataAnnotation attributes. While it’s preferable to place your DataAnnotation attributes in the Entity class itself, the .net framework does not support “partial properties”, the same way it does support “partial classes and methods”. Since metadata is supposed to be attached to a property defining the column, it’s relocated into this “Entity Metadata class”

This restriction applies only to properties associated with columns in the database. You can create calculated or custom properties in the actual Entity class and attach DataAnnotation attributes to them directly.

Customizing rules at runtime

When attached to a property in code, attribute objects are metadata, and have a fixed value defined at compile time. Business rules are often based on information available at runtime. For example, a date range validator may need a rule like “from 6 months ago until yesterday”. The runtime information here is today’s date, from which 6 months ago and yesterday are calculated. If you were limited to using metadata alone, you would have to create a new attribute class to cover each case like this.

BLD lets you customize the business rules as they are used. Each Entity class can host the CustomizeDataField() method. It is passed a description of available business rules, along with the DataField name. You write code that modifies the description of business rules. Many rules are still created by instantiating an attribute object. However, the attribute is no longer established as metadata, so you can calculate the appropriate values for its properties.

[C#]
public void CustomizeDataField(DESDA.ActiveDataField activeDataField)
{
  if (activeDataField.DataField == "PurchaseDate")
  {
    DESDA.RangeAttribute rangeAttribute = activeDataField.GetEditableValidationAttribute<DESDA.RangeAttribute>(true);
    rangeAttribute.Minimum = DateTime.Today.AddMonths(-6);
    rangeAttribute.Maximum = DateTime.Today.AddDays(-1);
  }
}
[VB]
Public Sub CustomizeDataField(activeDataField As DESDA.ActiveDataField )
  If activeDataField.DataField = "PurchaseDate" Then
    Dim rangeAttribute As DESDA.RangeAttribute = activeDataField.GetEditableValidationAttribute(Of DESDA.RangeAttribute)(True)
    rangeAttribute.Minimum = DateTime.Today.AddMonths(-6)
    rangeAttribute.Maximum = DateTime.Today.AddDays(-1)
  End If
End Sub

Data Access Objects

Since a Data Access Object is an important aspect of a multilayered application, you may already have one. If so, it can be used. However, the User Interface Layer needs a way to communicate with it. When using ASP.NET Web Forms, the correct tool is a DataSource control such as the ObjectDataSource or one you create for your Data Access Object classes.

BLD includes its own Data Access Object classes in case you don’t have one, or want to take advantage of some features “BLD DataAccessObjects” includes: paging, caching, a powerful filtering system, etc. BLD DataAccessObjects include support for Entity Framework, LINQ to SQL, and ADO.NET. It can be extended to handle other Data Access Layer technologies through subclassing.

When using ASP.NET Web Form, use the EntityDAODataSource control. It enforces a separation of concerns by preventing the Web Forms programmer from knowing too many details of the underlying Data Access Object when setting it up. Generally they specify the Entity class name, name of the Select method, and any EntityFilters it needs.

Building the User Interface Layer

Field Templates and DataAnnotation attributes

Note: While this implementation is specific to ASP.NET Web Forms, it provides a model for all platforms to use.

The Web Forms developer no longer adds textboxes and validator controls to the Web Forms file. Instead, they have a layer separating the Web Form from the BLL, built upon Field Templates. A Field Template is a user control that hosts the actual data entry and validation controls. There is a library of them, with Field Template files covering a wide variety of data types.

The Field Template’s job is to ensure that all relevant business rules are followed. It asks the BLL for an object describing the DataField it’s supposed to support. It modifies the data entry control to fit the business rules. For example, it may use a DateTextBox when the data type is a date. Validation is handled through the BLDDataFieldValidator control, which is placed within the Field Template. It converts all validation DataAnnotation attributes into Validator web controls (using the more powerful DES Validation Framework) ensuring the user interface has all validation business rules applied.

BLD provides a rich framework of Field Template base classes already familiar with the DataAnnotation attributes included with BLD, so that the actual user control files contain only the actual controls, and code that registers them.

Here is the content of an actual Field Template user control file:

[C#]
<%Control Language="C#" Inherits="PeterBlum.DES.BLD.CurrencyEditFieldTemplate" %>
<script runat="server">
protected void Page_Init(object sender, EventArgs e) { SetUpEditableDataControl(CurrencyTextBox1); SetUpBLDDataFieldValidators(BLDDataFieldValidators1); }
</script> <des:CurrencyTextBox ID="CurrencyTextBox1" runat="server" /> <des:BLDDataFieldValidators ID="BLDDataFieldValidators1" runat="server" />
[VB]
<%Control Language="VB" Inherits="PeterBlum.DES.BLD.CurrencyEditFieldTemplate" %>
<script runat="server">
Protected Sub Page_Init(sender As object, e As EventArgs) SetUpEditableDataControl(CurrencyTextBox1) SetUpBLDDataFieldValidators(BLDDataFieldValidators1) End Sub
</script> <des:CurrencyTextBox ID="CurrencyTextBox1" runat="server" /> <des:BLDDataFieldValidators ID="BLDDataFieldValidators1" runat="server" />

Back on the Web Form, the developer adds a BLDDataField control, specifying the DataField’s name. It uses a factory to load the correct Field Template. If you have several Field Template files for a single data type to provide different user interfaces, set the name of the desired one in its UIHint property.

<des:BLDDataField id="Name" runat="server" DataField="CategoryName" />
<des:BLDDataField id="Description" runat="server" 
  DataField="Description" UIHint="MultilineText" />

While the BLDDataField control lacks the name of the Entity class associated with the DataField, it learns the Entity class through DataSource and DataBound controls, which are described in the next sections.

DataSource controls and Data Access Objects

Microsoft developed the DataSource controls to give Web Forms developers a way to handle CRUD actions. Two popular controls, LinqDataSource and EntityDataSource, have the Web Form developer create business logic code in the Web Form itself. Those are not good choices and cannot be used with Data Access Objects.

When using BLD DataAccessObjects, use the EntityDAODataSource control that comes with BLD. It knows how to create an instance of the appropriate Data Access Object class, collect data from the Field Templates, and pass that data to the Update, Insert, and Delete methods on the BLD DataAccessObject. Similarly, it knows how to invoke a query through “Select methods” defined on the BLD DataAccessObject.

When using your own Data Access Object, use the ObjectDataSource control. (BLD includes an enhanced ObjectDataSource that is recommended.) Once again, this control delegates all actual CRUD activity to methods on your Data Access Object.

Two-way databinding through DataBound controls

Microsoft developed the DataBound controls to give Web Forms developers a way to send and receive data from web controls they contain. You’ll recognize them better by their names: GridView, DetailsView, ListView, and FormView. You probably already know how to use them: add the appropriate controls into their <Template> nodes. In the case of BLD, you add BLDDataField controls into <Template> nodes.

One important job of the DataBound control is to intercept commands and invoke the action of those commands. Commands are strings like “Update”, “Insert”, “Next”, and “Cancel” that are usually defined in a button’s CommandName property.

Example using the “Update” command

Suppose your FormView control’s <EditTemplate> node contains a Button with CommandName="Update". When the button is invoked, a postback occurs and the button bubbles its command up to the FormView which recognizes “Update” and takes the desired action.

The Update command makes the FormView request data from each Field Template. The Field Template is passed a dictionary object to which it adds the DataField name it represents and data value it hosts. Once all data has been collected, the FormView calls the DataSource’s ExecuteUpdateCommand method with the dictionary and awaits a response. That response indicates if an exception was raised. If so, the Form View knows to preserve the current edit mode, updating the ValidationSummary control with the errors. If no error occurs, it changes the form to reflect completion.

Putting all of the Layers together

Selecting data: Queries

Chart showing layers when using queries

Saving data: Updates, Inserts and Deletes

Chart showing layers when using updates, inserts, and deletes

Widgets

BLD has numerous other controls to construct a data oriented user interface, including filtering, sorting, paging, and command button controls. These controls are designed to comply with your business rules. The BLDWidgetsView control can host all of these as a kind of control panel to manage the data. There are individual controls to handle filtering and buttons too.

  • The BLDDataButtons control will show buttons like New, Edit, and Delete, hiding those where the security restrictions prevent adding, editing, or deleting.
  • A Sorting dropdownlist within the BLDWidgetsView will get the names from the BLL, where each DataField’s description includes a property that indicates if its sortable or not, optionally determined by the SortableColumnAttribute DataAnnotation attribute.
  • The BLDColumnTitle control will also determine if it supports sorting from the same data in the BLL.
  • The BLDPatternForFilterFields control builds a filtering interface, determining which DataFields should appear from business rules.
  • The BLDFilterSummary control displays the filters that have been applied, and lets the user remove some or all of them.
Widgets example

The above was created using this markup.

<table><tr><td style="width:300px;vertical-align:top;">
<des:BLDPatternForFilterFields ID="Filters" runat="server" TemplateTheme="Hyperlinks"
  PatternTemplateName="Filters Stacked Format" AutoGenerateButtons="None" />
</td><td style="vertical-align:top;">
<des:BLDListView ID="ListView1" runat="server" DataSourceID="DataSource" />
<des:BLDWidgetsView ID="ListViewWidgets" runat="server" PagedControlID="ListView1" >
  <Widgets>
    <des:NextPreviousPagerWidget/>
    <des:NewCommandButtonWidget/>
  </Widgets>
</des:BLDWidgetsView>
</td></tr></table>
<des:EntityDAODataSource id="DataSource" runat="server" EntityTypeName="Category" />

Conclusion

BLD provides substantial tools for building the user interface and business rules of a multilayered business application. You can’t see it here, but this framework is huge as it covers a large section of application building. Treat it like learning any major new technology or API. A good way to learn it is by using the BLD Guided Tour. From there, use both the online site and the 2000+ page Users Guide to dig deeper.

For more, go to BLD Product Overview and Learning BLD.