Introduction to Business Rules on individual DataFields

This series looks at the Business Logic Layer of an application from how my Peter’s Business Logic Driven UI (“BLD”) implements it. Use the “Understanding the BLL” Category to see all articles.

It’s time to dive into a big subject: the business rules on individual DataFields (properties defined in the Entity class). Business rules include validation, declaring the real-world data type, and so much more as shown in the chart below. Like any good object oriented implementation, business rules are described using objects. Microsoft introduced the approach: DataAnnotation attributes for its ASP.NET Dynamic Data, Silverlight, and MVC offerings.

To review, Attributes apply metadata to properties and classes. They are created by subclassing System.Attribute. They are used by adding a language specific syntax above the declaration of a class, property, method, etc. In the case of applying business rules to DataFields, these Attributes are applied to properties within the Entity class and Entity metadata class.

In this example, you see the RequiredAttribute, StringLengthAttribute, and CustomValidationAttribute, all supplied in the .net framework’s System.ComponentModel.DataAnnotations namespace.

[C#]

public class CategoryMetadata
{
   [Required()]
   [StringLength(30)]
   [CustomValidation(MethodName="CheckForDuplicateCategoryNames")]
   public object CategoryName { get; set; }
}

[VB]

Public Class CategoryMetadata
   <Required()> _
   <StringLength(30)> _
  <CustomValidation(MethodName := "CheckForDuplicateCategoryNames")> _
  Public Property CategoryName As Object
    Get
      Return Nothing
    End Get
    Set
    End Set
  End Property
End Class

Despite being shown here as metadata, business rules really don’t care where they come from. It’s perfectly fine to create the RequiredAttribute programmatically instead of attaching it to a property. BLD provides a mechanism to do this through its DataFieldDescriptor objects which host all business rules. As DataFieldDescriptors are created, they either get the DataAnnotation attributes from metadata or your event handler which creates them programmatically. DataAnnotation attributes can also be created as the situation demands. See “Customizing Business Rules at runtime”.

Let’s boil it down to this:

  • DataAnnotation attributes are objects which host values for business rules.
  • You can create them.
  • Microsoft has created a few of them for you.

BLD has also created some for you. Let’s introduce you to the many predefined business rules you have when using BLD.

Validation rules – When you think of business logic, validation comes to mind. The .net framework gets us started with a standard way to create validation rules, by subclassing System.ComponentModel.DataAnnotations.ValidationAttribute.

Due to DES’s very powerful Validation Framework, BLD introduces richer versions of those supplied in .net, and adds many more. See “Understanding ValidationAttributes”.

Even though they supply validation, ValidationAttributes can offer other features. For example:

  • Use the DESDA.InjectionSecurityAttribute to determine illegal content supplied by hackers, log it, and block further access to the page. (Normally validation only reports back to the user an issue.)
  • Use the DESDA.CharacterSetAttribute not only to define the character set allowed by a string-type field, but also to inform the TextBox control how to create keyboard filtering rules to match.

Data types – Each property has a type, such as string, integer or boolean, that mimics the type from the Column in the table (nvarchar, integer). That type is often not specific enough for developing a user interface or validation rules. For example, a double can be used as a currency, percentage, duration, longitude, etc. DataTypeAttributes let you redefine the type and provide more specific validation and formatting rules.

Once again, the .net framework gets us started with a standard way to describe a data type: the System.ComponentModel.DataAnnotations.DataTypeAttribute. BLD handles many new cases, like Measurement, DbImage, Duration, and Enumerated. These attributes have a rich set of tools to create your business rules. Most DataTypeAttributes have validation rules too. For example, the DESDA.EmailAddressAttribute creates a regular expression for the email address pattern.

See “Understanding DataTypeAttributes”.

Textual rules – Provide user friendly and localized names for fields, default strings for descriptions (such as used in a tooltip or hint) and for prompts with the DESDA.DisplayNameAttribute and DESDA.DescriptionAttribute.

Data value rules – Provide a default value for the DataField when creating a new record with the DefaultValueAttribute. Provide string formatting rules (to convert a date or number) with the DisplayFormatAttribute. (Both of these are from System.ComponentModel.DataAnnotations.)

Security rules – Associate restrictions based on user roles to Entity classes and DataFields by adding the DESDA.TableRestrictionAttribute and DESDA.ColumnRestrictionAttribute to your business logic. The user interface changes as a restricted feature is requested, whether to hide the feature or provide an alternative. (The DESDA.TableRestrictionAttribute is an example of a DataAnnotation attribute that goes on the Entity class itself, not a DataField. DESDA.DisplayNameAttribute and a few others can also provide business rules this way.)

Calculation rules – Use the DESDA.CalculationDescriptorAttribute to describe the underlying calculation on a property. The user interface can interpret it to create interactive calculations on screen.

Foreign key rules – Use the DESDA.ForeignKeyQueryAttribute to define filters and sort order on the lists that show elements of a foreign table. To avoid querying the same data every time, establish caching requirements with the DESDA.CacheListAttribute.

Dependency rules – Marks a DataField as dependant on another with a specific rule defined with a DependencyAttribute. Dependencies enable validation rules, such as a field is only required when another field has a value. The user interface can also use dependencies to change the appearance of, or hide, a field based on the dependency’s rules.

Sorting rules – Use the DESDA.SortableColumnAttribute to identify if a DataField can be sorted or not. The user interface uses this to establish its sorting interface, such as column titles that change sort order when clicked.

Scaffolding rules – “Scaffolding” allows a user interface to be populated with DataFields automatically, using the same layout for each DataField shown. The DESDA.ScaffoldColumnAttribute indicates if the DataField is shown when using Automatic Scaffolding and in what order to place it.

DataField categories – Use the System.ComponentModel.CategoryAttribute on DataFields to assign one or more category names with the DataField. BLD’s user interface controls support categories with Automatic Scaffolding and to select a custom CSS class or style for an element of its Template (called “Named Styles”).

Filtering rules – The DESDA.FilterAttribute determines if and when a DataField can be added to a filtering user interface. The DESDA.RangeEntityFilterPickerAttributes describe pick lists of values for numeric and date DataFields seen so often in sales websites (like pick a price range: $0-$19, $20-$49, $50-$99.) See “FilterAttributes”.

Even with over 50 DataAnnotation attributes defined between BLD and the .net framework, this doesn’t cover all cases. You should create anything you don’t find here.

In the next few topics, we’ll look more carefully at some of the attribute classes that you may want to subclass for expansion.

No Comments