Home     About PeterBlum.com     Policies     Download a Licensed Product     Newsletter

Peter's Business Logic Driven UI
DataAnnotation Attributes: Implementing your business logic on columns and tables
Back to Product Overview  |  Next topic | Language preference:

Each table is recreated as an object called an Entity class. Each column of the table becomes a property of the Entity class called a DataField. You can add properties for calculated fields too. This becomes the framework where you add business logic associated with columns and the table itself.

An Attribute allows the programmer to annotate a class or property with "metadata". Within BLD, Attributes describe your business rules and annotate the properties of your Entity classes. These are called DataAnnotation Attributes.

Microsoft's DataAnnotation Attribute classes from the System.ComponentModel.DataAnnotations namespace get you started.

BLD introduces improved versions of most of those Attributes and covers many new business logic cases within its own PeterBlum.DES.DataAnnotations namespace.

Customizing attributes at runtime Business logic often needs to reflect the live data, such as a validation range for a birthdate may change its end date based on today's date. Attributes have fixed rules as they are compiled into your code's metadata. BLD addresses this issue by providing a programmatic way to describe the business rules. As the caller requests business logic, some rules come from attributes while others come from code.
public class Product
   [DESDA.CharacterSet(LettersLowercase=true, LettersUppercase=true, Digits=true,  
      Space=true, DiacriticLetters=true, OtherCharacters="'",
      ErrorMessage="Illegal character", 
      SummaryErrorMessage="{LABEL} has an illegal character.")]
   [DESDA.DisplayName("Product name", ShortDisplayName="Name")]
   public string ProductName { get; set; }

   [DESDA.CurrencyDataType(AllowNegatives=false, UseCurrencySymbol=true, MaxWholeDigits=4)]
   [DESDA.Description("The price of one unit")]
   [DESDA.DisplayName("Unit Price")]
   public System.Nullable<decimal> UnitPrice { get; set; }

   [DESDA.DisplayName("Value of Stock")]
   [DESDA.CalculationDescriptor("if (Not Discontinued) then {UnitPrice * UnitsInStock} else novalue")]
   [DESDA.ColumnRestriction("Customer", DESDA.DenyAccess.All)]
   [DESDA.SortableColumn(SortExpression="UnitPrice * UnitsInStock", Sortable=true)]
   public decimal ValueOfStock
         if (!Discontinued)
            if (UnitPrice.HasValue && UnitsInStock.HasValue)
               return UnitPrice.Value * UnitsInStock.Value;
         return 0.0M;
ProductName and UnitPrice are existing fields on the Product table
while ValueOfStock is a calculated field.

Data Type Attributes

Each property's type (like Integer, String, and DateTime) are usually too broad to describe the actual data of the column. A string can represent numerous types, such as HTML, a phone number, or a name. Your business logic needs to identify the specific type because there are rules specific to them. For example, a phone number is a pattern that needs to be checked against a regular expression pattern and that pattern may differ based on the address location.

The System.ComponentModel.DataAnnotations.DataTypeAttribute helps, although it provides a relatively short list of data types. BLD includes numerous DataType Attribute classes, many with a variety of properties to customize the business rules. You can also create your own DataType attributes.

[DESDA.CurrencyDataType(AllowNegatives=false, UseCurrencySymbol=true, MaxWholeDigits=4)]
public System.Nullable<decimal> UnitPrice { get; set; }

[DESDA.DateDataType(ErrorMessage="This is an error",
   SummaryErrorMessage="The {LABEL1} is an illegal date.", DisplayOrder=0)]
public DateTime BirthDate { get; set; }

public int OutputMode { get; set; }

public string TitleOfCourtesy { get; set; }
DataTypeAttribute type Description
DESDA.DateDataTypeAttribute Dates
DESDA.TimeOfDayDataTypeAttribute Time of day
DESDA.DateTimeDataTypeAttribute Date and Time of day together
DESDA.DurationDataTypeAttribute Durations
DESDA.AnniversaryDataTypeAttribute Dates showing month and date, but no year.
DESDA.MonthYearDataTypeAttribute Dates showing month and year, but no date.
DESDA.IntegerDataTypeAttribute Integers
DESDA.DecimalDataTypeAttribute Floating point numbers
DESDA.CurrencyDataTypeAttribute Currency numbers
DESDA.PercentDataTypeAttribute Numbers representing percentages
DESDA.IntegerMeasurementDataTypeAttribute Integers representing measurements. Includes labels to describe the measurement units.
DESDA.DecimalMeasurementDataTypeAttribute Floating point numbers representing measurements. Includes labels to describe the measurement units.
DESDA.EnumeratedAttribute For integer fields that can be represented by an enumerated type.
DESDA.EnumeratedStringAttribute For string fields that can be represented by an enumerated type. The field should store a specific list of possible strings.
DESDA.ListOfValuesDataTypeAttribute A more powerful version of the DESDA.EnumeratedAttribute that allows you to gather data from various resources and display that data in different ways. For example, a Country DataField could get its data from an XML file and display either the full name or abbreviated name.
DESDA.DbImageDataTypeAttribute For binary fields that contain an image, including gif, jpg, png, tiff, and bmp.
DESDA.EmailAddressDataTypeAttribute For text fields containing email addresses.
DESDA.UrlAsImageDataTypeAttribute For text fields containing a URL to an image.
DESDA.UrlDataTypeAttribute For text fields containing a URL.
DESDA.CreditCardNumberAttribute Use when the string contains a credit card number.
DESDA.ABARoutingNumberAttribute Use when the string contains an ABA Routing Number.
DESDA.DataTypeAttribute and System.ComponentModel.DataAnnotations.- DataTypeAttribute Provides numerous additional types.

Validation Attributes

Validation is perhaps the first type of business rule you think of. The System.ComponentModel.DataAnnotations namespace provides you with several rules, but this hardly covers the real world cases you will face. BLD improves upon the originals and is designed for expansion when you have additional cases.

Here are a few improvements made with BLD's Validator Attributes:

  • Interacts with a factory that creates different Validator classes based on the user interface (or lack thereof). That factory is prepopulated to support ASP.NET Web Forms (using DES Validation framework validators) and UI neutral validation. You could create validators for MVC, Silverlight, etc. that are delivered by the factory.
  • Covers cases that involve multiple columns, such as comparing the value of column A to column B.
  • Due to the richness of DES Validation Framework validators, these attributes are also rich with properties to customize the rules.
  • When combined with the DependencyAttributes (below), validation rules can be enabled based on the values of other columns. The DES Validation Framework uses the term "Enabler" to describe this capability.
  • Their error message strings employ tokens that get substituted with live data and the actual field labels shown in the Web Form. This reduces the need to create error messages within the UI layer.
[DESDA.Range("1900-01-01", "1999-12-31", DisplayOrder=5)]
[DESDA.DateDataType(ErrorMessage="This is an error", 
   SummaryErrorMessage="The {LABEL} is an illegal date.", DisplayOrder=0)]
[DESDA.CompareTwoColumns("HireDate", PeterBlum.DESDA.ConditionOperator.LessThan, 
public object BirthDate { get; set; }

[DESDA.DateDataType(ErrorMessage="This is an error", 
   SummaryErrorMessage="The {LABEL} is an illegal date.")]
public object HireDate { get; set; }
ValidationAttribute type Description
All BLD DataTypeAttributes listed above. Ensure that a text entry of a value can be converted to the expected data type.
DESDA.RequiredAttribute The field requires a value. It cannot be blank.
DESDA.RangeAttribute Establish a range.
DESDA.CompareToValueAttribute Compare the value of this field to a value assigned to its ValueToCompare property.
DESDA.RegularExpressionAttribute Match a string field value to a specific pattern using a regular expression.
DESDA.StringLengthAttribute Impose limits on the number of characters permitted in a string field.
DESDA.CompareTwoColumnsAttribute Compares the value of this field with another field.
DESDA.DifferenceAttribute Compare the value of two fields to determine how the difference between their values compares to a value in the DifferenceValue property.
DESDA.StringListAttribute Compares a string to a list of strings to see if there is a match.
DESDA.InjectionSecurityAttribute Look for signs of hackers employing SQL Injection and/or Cross Site Scripting attacks. More
DESDA.CharacterSetAttribute Use on string fields that restrict the character set. The user interface can use this attribute to block entry of illegal characters in a textbox.
DESDA.SpecialDatesAttribute Defines a list of dates and associated data. Validates unselectable dates as invalid and provides both selectable and unselectable dates to the user interface layer for presentation.
DESDA.SpecialTimesAttribute Defines a list of times and associated data. Validates unselectable times as invalid and provides both selectable and unselectable times to the user interface layer for presentation.
DESDA.EmailDomainsValidationAttribute Use with an email address to either require or invalidate specific domains. It compliments the DESDA.EmailAddressDataTypeAttribute.
DESDA.FileExtensionValidationAttribute Use when evaluating a Url that must have a specific file extension or extensions. It compliments the DESDA.UrlDataTypeAttribute.
DESDA.CustomValidationAttribute Makes it easy to add a new validation business rule without creating a ValidationAttribute.
This attribute supports validation on individual properties and on the overall Entity class object (checking several properties together).
Column dependencies

BLD introduces the "DependencyAttribute". Apply it to columns where another column determines if this column is active or not. For example, a date column may not be available until a boolean column (represented by a checkbox) is true (checked). The dependency has two effects on the user interface. It disables (or hides) the data entry control and it disables its associated validators.

When server side code validates before updating or inserting the Entity, it checks with the DependencyAttribute prior to running the ValidatorAttribute's validation rule.

public string CategoryName { get; set; }

public bool Discontinued { get; set; }

public string Description { get; set; }

[DESDA.CompareBooleanDependency(DataField="Discontinued", ValueToCompare=false)]
public System.Nullable<decimal> UnitPrice { get; set; }
More BLD Attributes
Attribute type Description
DESDA.ColumnRestrictionAttributeAssociates security restrictions with a column based on user roles. More
DESDA.TableRestrictionAttributeAssociates security restrictions with a table based on user roles. More
DESDA.CalculationDescriptorAttributeExposes the logic of a numeric calculation so the user interface can interactively update the DataField as users edit values in the calculation. More
DESDA.DisplayNameAttributeGives a user friendly label for the DataField name. It provides two versions of the string: normal and short. Its value can be localized. More
DESDA.DescriptionAttributeA description shown through hints or tooltips. It also provides a second string to be used as Prompt. Its value can be localized. More
DESDA.SortableColumnAttributeDetermines if the column should support sorting user interfaces and its Sort Expression. Columns determine sorting without it based on their datatype. Use this to override that default.
DESDA.ForeignKeyQueryAttributeUsed on Foreign Key fields to establish a filter and sort order for lists shown to the user. More
DESDA.FilterAttributeIdentify DataFields that should offer filter user interfaces. More
DESDA.RangeEntityFilterPickerAttribute and DESDA.DateRangeEntityFilterPickerAttributeProvide a pick list of ranges to display in a filtering user interface.
DESDA.ScaffoldColumnAttributeGenerally used by the user interface to determine the presence and order of this column when the programmer wants business logic to dictate the columns shown. More
DESDA.UIHintAttributeDetermines which FieldTemplate to use. Expanded to allow setting the FieldTemplate ("UIHint") and properties on that FieldTemplate based on the mode (readonly, edit, insert).
DESDA.CacheListAttributeUsed on Enumerated and Foreign Key fields to retain their lists in the Application Cache instead of recalling their elements from the database with each page request.
DESDA.AttributeSourceAttribute Shares Attributes between properties. Makes setting up Entity classes for Views easier and less errorprone by ensuring each property in the View’s Entity has the same business logic as the Entity from which is was formed.

System.ComponentModel.DataAnnotation Attributes used by BLD

You can use almost any Attribute supplied by System.ComponentModel.DataAnnotation that has a replacement in the prior lists. In addition, here are several unique to System.ComponentModel.DataAnnotations.

Attribute type Description
DefaultValueAttributeProvides a default value for fields when the user starts a new row in the table. More
DisplayFormatAttributeAssists the Field Template when it formats a value as a string. Provides these properties: NullDisplayText (used when a DataField value is null and needs to be displayed in a label), DataFormatString (applied with String.Format to the value), ConvertEmptyStringToNull (used when saving a blank entry), and ApplyFormatInEditMode.
DisplayColumnAttributeSpecifies which field of the Entity class to display (in filters or in foreign key links). If not assigned, BLD uses the first column of type string that it finds. It also lets you change the default sorting, to specify a different field and sort order.
CategoryAttributeAssists in selecting data fields by a group. It is used with the NamedStyles feature to change the style sheet based on fields of specific categories and by the Automatic Scaffolding to build lists of fields based on a group.
EditableAttributeOffers one way to restrict users from editing specific DataFields. If you have role-based security, use the ColumnRestrictionAttribute instead of the EditableAttribute.
ScaffoldTableAttributeLets the business logic dictate if the table should be available in a list shown to the user. More

Back to Product Overview  |  Next topic