MSDN Magazine - February 2009 - (Page 41) 4). Note in the SQL in Figure 4 that the string lengths match the Figure 4 Generating DDL Code CREATE TABLE [dbo].[Address]( [id] [bigint] IDENTITY(1,1) NOT NULL, [StateOrProvince] [nvarchar](100) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, [Country] [nvarchar](100) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, [PostalCode] [nvarchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, [TimeZone] [nvarchar](100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, [Address1] [nvarchar](250) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, [Address2] [nvarchar](100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, [City] [nvarchar](250) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, PRIMARY KEY CLUSTERED ( [id] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] definition from the [MaximumStringLength] attributes on the Address class. Likewise, the NULL / NOT NULL values follow from the [Required] attributes on the Address class. We’ve invested in some infrastructure that derives the database structure from the validation attributes on the Domain Model objects, but we still have the matter of client-side validation and client-side appearance. We’d like to perform the simple input validations inside the browser and mark the required field elements in some way for a better user experience. The solution that my team arrived at was to make the HTML rendering of input elements aware of the validation attributes. (For context, we’re using the ASP.NET Model View Controller, or MVC, Framework Beta1 with the Web Forms engine as our view engine.) Figure 5 shows what the markup might look like for an Address View in our system. TextBoxFor and DropDownListFor are little HTML helpers in the common base view that are used for all views in our MVC architecture. The signature of TextBoxFor is shown here: public static TextBoxExpression TextBoxFor ( this IViewWithModel viewPage, Expression<Func > expression) where TModel : class { return new TextBoxExpression ( viewPage.Model, expression); } Figure 5 Address View Markup m.Address1).Width(300)%> m.Address2).Width(300) %> m.City).Width(140) %> m.StateOrProvince).FillWith(m => m.StateOrProvinceList) %> m.PostalCode).Width(80) %> m.Country).FillWith(m => m.CountryList) %> m.TimeZone).FillWith(m => m.DovetailTimeZoneList) %> The important thing to note in this code is that the input argument is an Expression (Expression<Func > to be precise). While constructing the actual HTML for the textbox, the TextBoxExpression class will: 1. Parse the Expression and find the exact PropertyInfo object for the bound property. 2. Interrogate that PropertyInfo for the existence of the validation attributes. 3. Render the HTML for the textbox accordingly. We simply added a class called required to all HTML elements that are bound to properties marked with the [Required] attribute. Likewise, if we found a [MaximumStringAttribute] on a bound property, we set the maxlength attribute of the HTML textbox to match the attribute and limit the user input to allowable lengths. The resulting HTML looks something like this: Address: Domain-Centric Validation The .NET Framework makes it nearly trivial to add declarative field-level validation in the user interface with tools such as the ASP.NET Validator controls. All the same, I think it’s advantageous to place validation logic on the actual domain model classes, or at least close by in domain services, for these reasons: 1. Validation logic is a business logic concern, and I’d prefer that all business logic be contained in the business logic classes. 2. Putting the validation logic into the domain model or domain services disconnected from the user interface potentially reduces duplication across screens and allows the same validation logic to be exercised in non-user interface services (Web services, for example) exposed by the application (Saying It Once and Only Once, yet again). 3. It is far easier to write unit and acceptance tests against validation logic in the model than it is to test that same logic implemented as part of the user interface. msdnmagazine.com The appearance of required fields is easy to control simply by editing the appearance of the CSS class required (we set the color of required fields on the screen to a light blue). We did the actual client-side validation with the jQuery Validation plug-in, which, conveniently enough, simply looks for the existence of the required class on input elements. The maximum length of a text element is enforced simply by setting the maxlength attribute on the input elements. By no means was this a complete implementation. Building the actual implementation over time wasn’t that difficult. The hard part was thinking through ways to eliminate repetitive metadata and coding in the multiple layers. I’m sure that many teams will not be keen on the way that my team generated the database from the object model, but that’s OK because my real goal is just to give you some ideas about how you might use the Say it Once and Only Once Principal to streamline your own development efforts. Sensible Defaults In the previous section, I showed a very small example (via an AddressMap class) of expressing object relation mapping (ORM) with Fluent NHibernate. Here’s a slightly more complicated example that expresses a reference from a Site class to Address objects: February 2009 41 http://www.msdnmagazine.com
Table of Contents Feed for the Digital Edition of MSDN Magazine - February 2009 MSDN Magazine - February 2009 Contents Toolbox CLR Inside Out Data Points Cutting Edge Patterns In Practice Best Practices .Net Interop "Oslo" Basics Patterns Silverlight Under The Table Foundations Windows With C++ .NET Matters Going Places { End Bracket } MSDN Magazine - February 2009 MSDN Magazine - February 2009 - (Page Splash1) MSDN Magazine - February 2009 - Contents (Page Cover1) MSDN Magazine - February 2009 - Contents (Page Cover2) MSDN Magazine - February 2009 - Contents (Page 1) MSDN Magazine - February 2009 - Contents (Page 2) MSDN Magazine - February 2009 - Contents (Page 3) MSDN Magazine - February 2009 - Contents (Page 4) MSDN Magazine - February 2009 - Contents (Page 5) MSDN Magazine - February 2009 - Contents (Page 6) MSDN Magazine - February 2009 - Contents (Page 7) MSDN Magazine - February 2009 - Contents (Page 8) MSDN Magazine - February 2009 - Contents (Page 9) MSDN Magazine - February 2009 - Contents (Page 10) MSDN Magazine - February 2009 - Toolbox (Page 11) MSDN Magazine - February 2009 - Toolbox (Page 12) MSDN Magazine - February 2009 - Toolbox (Page 13) MSDN Magazine - February 2009 - Toolbox (Page 14) MSDN Magazine - February 2009 - CLR Inside Out (Page 15) MSDN Magazine - February 2009 - CLR Inside Out (Page 16) MSDN Magazine - February 2009 - CLR Inside Out (Page 17) MSDN Magazine - February 2009 - CLR Inside Out (Page 18) MSDN Magazine - February 2009 - CLR Inside Out (Page 19) MSDN Magazine - February 2009 - CLR Inside Out (Page 20) MSDN Magazine - February 2009 - CLR Inside Out (Page 21) MSDN Magazine - February 2009 - CLR Inside Out (Page 22) MSDN Magazine - February 2009 - Data Points (Page 23) MSDN Magazine - February 2009 - Data Points (Page 24) MSDN Magazine - February 2009 - Data Points (Page 25) MSDN Magazine - February 2009 - Data Points (Page 26) MSDN Magazine - February 2009 - Data Points (Page 27) MSDN Magazine - February 2009 - Data Points (Page 28) MSDN Magazine - February 2009 - Data Points (Page 29) MSDN Magazine - February 2009 - Data Points (Page 30) MSDN Magazine - February 2009 - Cutting Edge (Page 31) MSDN Magazine - February 2009 - Cutting Edge (Page 32) MSDN Magazine - February 2009 - Cutting Edge (Page 33) MSDN Magazine - February 2009 - Cutting Edge (Page 34) MSDN Magazine - February 2009 - Cutting Edge (Page 35) MSDN Magazine - February 2009 - Cutting Edge (Page 36) MSDN Magazine - February 2009 - Cutting Edge (Page 37) MSDN Magazine - February 2009 - Cutting Edge (Page 38) MSDN Magazine - February 2009 - Patterns In Practice (Page 39) MSDN Magazine - February 2009 - Patterns In Practice (Page 40) MSDN Magazine - February 2009 - Patterns In Practice (Page 41) MSDN Magazine - February 2009 - Patterns In Practice (Page 42) MSDN Magazine - February 2009 - Patterns In Practice (Page 43) MSDN Magazine - February 2009 - Patterns In Practice (Page 44) MSDN Magazine - February 2009 - Patterns In Practice (Page 45) MSDN Magazine - February 2009 - Best Practices (Page 46) MSDN Magazine - February 2009 - Best Practices (Page 47) MSDN Magazine - February 2009 - Best Practices (Page 48) MSDN Magazine - February 2009 - Best Practices (Page 49) MSDN Magazine - February 2009 - Best Practices (Page 50) MSDN Magazine - February 2009 - Best Practices (Page 51) MSDN Magazine - February 2009 - Best Practices (Page 52) MSDN Magazine - February 2009 - Best Practices (Page 53) MSDN Magazine - February 2009 - Best Practices (Page 54) MSDN Magazine - February 2009 - Best Practices (Page 55) MSDN Magazine - February 2009 - Best Practices (Page 56) MSDN Magazine - February 2009 - .Net Interop (Page 57) MSDN Magazine - February 2009 - .Net Interop (Page 58) MSDN Magazine - February 2009 - .Net Interop (Page 59) MSDN Magazine - February 2009 - .Net Interop (Page 60) MSDN Magazine - February 2009 - .Net Interop (Page 61) MSDN Magazine - February 2009 - .Net Interop (Page 62) MSDN Magazine - February 2009 - "Oslo" Basics (Page 63) MSDN Magazine - February 2009 - "Oslo" Basics (Page 64) MSDN Magazine - February 2009 - "Oslo" Basics (Page 65) MSDN Magazine - February 2009 - "Oslo" Basics (Page 66) MSDN Magazine - February 2009 - "Oslo" Basics (Page 67) MSDN Magazine - February 2009 - "Oslo" Basics (Page 68) MSDN Magazine - February 2009 - "Oslo" Basics (Page 69) MSDN Magazine - February 2009 - "Oslo" Basics (Page 70) MSDN Magazine - February 2009 - "Oslo" Basics (Page 71) MSDN Magazine - February 2009 - Patterns (Page 72) MSDN Magazine - February 2009 - Patterns (Page 73) MSDN Magazine - February 2009 - Patterns (Page 74) MSDN Magazine - February 2009 - Patterns (Page 75) MSDN Magazine - February 2009 - Patterns (Page 76) MSDN Magazine - February 2009 - Patterns (Page 77) MSDN Magazine - February 2009 - Patterns (Page 78) MSDN Magazine - February 2009 - Patterns (Page 79) MSDN Magazine - February 2009 - Patterns (Page 80) MSDN Magazine - February 2009 - Patterns (Page 81) MSDN Magazine - February 2009 - Patterns (Page 82) MSDN Magazine - February 2009 - Patterns (Page 83) MSDN Magazine - February 2009 - Silverlight (Page 84) MSDN Magazine - February 2009 - Silverlight (Page 85) MSDN Magazine - February 2009 - Silverlight (Page 86) MSDN Magazine - February 2009 - Silverlight (Page 87) MSDN Magazine - February 2009 - Silverlight (Page 88) MSDN Magazine - February 2009 - Silverlight (Page 89) MSDN Magazine - February 2009 - Silverlight (Page 90) MSDN Magazine - February 2009 - Silverlight (Page 91) MSDN Magazine - February 2009 - Silverlight (Page 92) MSDN Magazine - February 2009 - Silverlight (Page 93) MSDN Magazine - February 2009 - Silverlight (Page 94) MSDN Magazine - February 2009 - Under The Table (Page 95) MSDN Magazine - February 2009 - Under The Table (Page 96) MSDN Magazine - February 2009 - Under The Table (Page 97) MSDN Magazine - February 2009 - Under The Table (Page 98) MSDN Magazine - February 2009 - Under The Table (Page 99) MSDN Magazine - February 2009 - Under The Table (Page 100) MSDN Magazine - February 2009 - Foundations (Page 101) MSDN Magazine - February 2009 - Foundations (Page 102) MSDN Magazine - February 2009 - Foundations (Page 103) MSDN Magazine - February 2009 - Foundations (Page 104) MSDN Magazine - February 2009 - Foundations (Page 105) MSDN Magazine - February 2009 - Foundations (Page 106) MSDN Magazine - February 2009 - Windows With C++ (Page 107) MSDN Magazine - February 2009 - Windows With C++ (Page 108) MSDN Magazine - February 2009 - Windows With C++ (Page 109) MSDN Magazine - February 2009 - Windows With C++ (Page 110) MSDN Magazine - February 2009 - .NET Matters (Page 111) MSDN Magazine - February 2009 - .NET Matters (Page 112) MSDN Magazine - February 2009 - .NET Matters (Page 113) MSDN Magazine - February 2009 - .NET Matters (Page 114) MSDN Magazine - February 2009 - Going Places (Page 115) MSDN Magazine - February 2009 - Going Places (Page 116) MSDN Magazine - February 2009 - Going Places (Page 117) MSDN Magazine - February 2009 - Going Places (Page 118) MSDN Magazine - February 2009 - Going Places (Page 119) MSDN Magazine - February 2009 - { End Bracket } (Page 120) MSDN Magazine - February 2009 - { End Bracket } (Page Cover3) MSDN Magazine - February 2009 - { End Bracket } (Page Cover4)
For optimal viewing of this digital publication, please enable JavaScript and then refresh the page. If you would like to try to load the digital publication without using Flash Player detection, please click here.