Home     About PeterBlum.com     Policies     Download a Licensed Product     Newsletter

DES Dynamic Data
Improving Business rules
Back

An Attribute allows the programmer to annotate a class or property with "metadata". Within ASP.NET Dynamic Data, Attributes annotate the classes that describe your tables with your business rules and some user interface elements.

Data types

DES introduces more data types. For example, the Measurement data type is for any type of measurement, like gallons, inches, decibels, etc.

Features of DES's extended Data type support:
  • There are new DataTypeAttributes specific to a datatype, such as TimeOfDayDataTypeAttribute. These also define a default FieldTemplate and a validation rule.
  • Many DataTypeAttributes have additional parameters to further customize them, such as the terminology used on the MeasurementDataTypeAttributes or the file extensions supported when selecting an image file.
[DES.CurrencyDataType(AllowNegatives=false,
  UseCurrencySymbol=true,
  MaxWholeDigits=4)]
public object UnitPrice { get; set; }

[DES.DateDataType(ErrorMessage="This is an error",
  SummaryErrorMessage="The {LABEL1} is an illegal date.",
  DisplayOrder=0)]
public object BirthDate { get; set; }
  • The DES.EnumeratedAttribute and DES.EnumeratedStringAttribute introduce support for enumerated types on integer and string columns. You supply a list of names shown the users that map to specific values.
    For integer fields, those names can come from an actual enumerated type.
[DES.EnumeratedAttribute(EnumeratedType=typeof(MyNamespace.OutputMode)]
public object OutputMode { get; set; }
DataTypeAttribute Description FieldTemplate
DES.DateDataTypeAttribute Dates "Date"
DES.TimeOfDayDataTypeAttribute Time of day "Time"
DES.DurationDataTypeAttribute Durations "Duration"
DES.AnniversaryDataTypeAttribute Dates showing month and date, but no year. "Anniversary"
DES.MonthYearDataTypeAttribute Dates showing month and year, but no date. "MonthYear"
DES.IntegerDataTypeAttribute Integers "Integer"
DES.DecimalDataTypeAttribute Floating point numbers "Decimal"
DES.CurrencyDataTypeAttribute Currency numbers "Currency"
DES.PercentDataTypeAttribute Numbers representing percentages "Percent"
DES.IntegerMeasurement-
  DataTypeAttribute
Integers representing measurements. Includes labels to describe the measurement units. "Measurement"
DES.DecimalMeasurement-
  DataTypeAttribute
Floating point numbers representing measurements. Includes labels to describe the measurement units. "Measurement"

Validation
There are ValidationAttributes for many validators within the DES Validation framework.

Validating data types often requires more rules that just "test that it is a [name your type] value". For example, currencies may not allow negative numbers or a decimal field should never have more than 3 decimal places. DES's validators already know about these extra rules. The DES-supplied ValidationAttributes let the database developer dictate them.

The native ASP.NET Validation framework cannot apply its predefined validators to columns in different naming containers. FieldTemplates are separate naming containers. So the CompareValidator cannot be setup to compare two columns. The DES implementation fully supports multiple column validation through its new ValidationAttributes for CompareTwoFields, Difference and more.

[DES.Required(DisplayOrder=1)]
[DES.Range("1900-01-01", "1999-12-31", DisplayOrder=5)]
[DES.DateDataType(ErrorMessage="This is an error",
   SummaryErrorMessage="The {LABEL1} is an illegal date.",
   DisplayOrder=0)]
[DES.CompareTwoColumns("HireDate",
   PeterBlum.DES.ConditionOperator.LessThan, DisplayOrder=10)]
public object BirthDate { get; set; }

[DES.DateDataType(ErrorMessage="This is an error",
   SummaryErrorMessage="The {LABEL1} is an illegal date.")]
public object HireDate { get; set; }

When defining validators, sometimes they need to be created based on live data. DES lets you create a ValidationAttribute based on that row by implementing the ICustomizeColumn interface in the Table's class or IUICustomizeColumn interface on the Master Page.

ValidationAttribute Type DES Validator it creates
DES.RequiredAttribute RequiredTextValidator or RequiredSelectionValidator depending on the data entry control used by the FieldTemplate
DES.RangeAttribute RangeValidator
DES.CompareToValueAttribute CompareToValueValidator
DES.RegularExpressionAttribute RegExValidator
DES.StringLengthAttribute TextLengthValidator
DES.CompareTwoColumnsAttribute CompareTwoFieldsValidator
DES.DifferenceAttribute DifferenceValidator
DES.StringListAttribute CompareToStringsValidator
DES.InjectionSecurityAttribute FieldSecurityValidator
DES.CharacterSetAttribute CharacterValidator
Note: FieldTemplates also apply this to their FilteredTextBox controls.
DES.DateDataTypeAttribute,
DES.TimeOfDayDataTypeAttribute,
DES.DurationDataTypeAttribute,
DES.AnniversaryDataTypeAttribute,
DES.MonthYearDataTypeAttribute,
DES.IntegerDataTypeAttribute,
DES.DecimalDataTypeAttribute,
DES.CurrencyDataTypeAttribute,
DES.PercentDataTypeAttribute,
DES.IntegerMeasurement-
  DataTypeAttribute,
DES.DecimalMeasurement-
  DataTypeAttribute
DataTypeCheckValidator with its DataType set appropriately.
DES.EmailAddressAttribute EmailAddressValidator
DES.CreditCardNumberAttribute CreditCardNumberValidator
DES.ABARoutingNumberAttribute ABARoutingNumberValidator

Column dependencies

DES 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.


public object CategoryName { get; set; }

[DES.RequiredDependency("CategoryName")]
public object Description { get; set; }

Character sets for textual columns

The table's metadata can identify a character set for a textual column by using the DES.CharacterSetAttribute. The FieldTemplates will adapt to that characterset, filtering out illegal characters as they are typed.


[DES.CharacterSet(LettersUppercase=false, LettersLowercase=false, Digits=true, Space=true, OtherCharacters="-()")]
public object PhoneNumber { get; set; }


Scaffolding rules
The ScaffoldColumnAttribute has been expanded to support repositioning the column in two ways:
  • Relative to the current position
  • After a specific column name

The Automatic Scaffolding engine (an implementation of the System.Web.UI.IAutoFieldGenerator interface) has been rewritten to handle far more than just the improved ScaffoldColumnAttribute. The Page Developer to include the IFieldGeneratorGuidance interface to programmatically specify the desired list of data fields and supporting rules for total control, and to avoid creating duplicate web forms when the only change is in the data field list.

void DES.IFieldGeneratorGuidance<DES.DataFieldInPattern, DES.BaseItemInPattern>.BeforeGeneration(
  DES.FieldGenerationArgs<DES.DataFieldInPattern, DES.BaseItemInPattern> pArgs)
{
 if ((pArgs.TableName == "Employees") && (pArgs.DataControlAction == DES.DataControlAction.List))
 {
   pArgs.ShowLongStringsInLists = true;
   pArgs.AddColumn("FirstName");
   pArgs.AddField(new DES.DataFieldInPattern("LastName", -1));
   pArgs.AddColumn("BirthDate");
   pArgs.AddColumn("PhotoPath");
 }
}

void DES.IFieldGeneratorGuidance<DES.DataFieldInPattern, DES.BaseItemInPattern>.AfterGeneration(
  DES.FieldGenerationArgs<DES.DataFieldInPattern, DES.BaseItemInPattern> pArgs)
{
 if ((pArgs.TableName == "Employees") && (pArgs.DataControlAction == DES.DataControlAction.Details))
 {
   pArgs.HideFieldByColumnName("Employees");
   pArgs.HideFieldByColumnName("Orders");
 }
}
Sub BeforeGeneration(ByVal pArgs As DES.FieldGenerationArgs(Of DES.DataFieldInPattern, DES.BaseItemInPattern)) _
   Implements DES.IPatternTemplateFieldGeneratorGuidance.BeforeGeneration
 If (pArgs.TableName = "Employees") And (pArgs.DataControlAction = DES.DataControlAction.List) Then
   pArgs.ShowLongStringsInLists = True
   pArgs.AddColumn("FirstName")
   pArgs.AddField(new DES.DataFieldInPattern("LastName", -1))
   pArgs.AddColumn("BirthDate")
   pArgs.AddColumn("PhotoPath")
 End If
End Sub

Sub AfterGeneration(ByVal pArgs As DES.FieldGenerationArgs(Of DES.DataFieldInPattern, DES.BaseItemInPattern))_
   Implements DES.IPatternTemplateFieldGeneratorGuidance.AfterGeneration
 If (pArgs.TableName = "Employees") And (pArgs.DataControlAction = DES.DataControlAction.Details) Then
   pArgs.HideFieldByColumnName("Employees")
   pArgs.HideFieldByColumnName("Orders")
 End If
End Sub

More Attributes
  • UIHintAttribute - Determines which FieldTemplate to use. Expanded to allow setting the FieldTemplate ("UIHint") and properties on that FieldTemplate based on the mode (readonly, edit, insert).
  • DisplayNameAttribute - Assigns the name of the data field shown to the user. Expanded to support DES's String Lookup Manager for localization.
  • DescriptionAttribute - A description shown through hints or tooltips in FieldTemplates. Expanded to support DES's String Lookup Manager for localization.
  • CacheListAttribute - When the FieldTemplate uses a ListBox or DropDownList to show items of an Enumerated type or ForeignKey, use this to cache the list.
  • SortableColumnAttribute - Determines 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.

Changing attribute values at the page level

Attributes are retrieved as the MetaColumn objects are created, which only happens once per application start. Once established, they are unchangable. Yet they have properties that you may want to edit while building the page such as IsRequired, IsReadOnly, DefaultValue, MaxLength, and the ValidationAttributes.

Being global data, the MetaColumn class must never be edited by page-level code. DES resolves this by offering the ModifiableColumn property on each FieldTemplate. It contains a copy of the attribute values that you can edit at the page-level by implementing the ICustomizeColumn or IUICustomizeColumn interfaces.


Back