18
Dec

Dynamic Data: Associated Types And The Models They Love

In the last article we introduced the ContextConfiguration class and its MetadataProviderFactory property. We also saw that if a provider factory isn’t explicitly set then an instance of the AssociatedMetadataTypeTypeDescriptorProvider class will be used. What we didn’t discuss is what an “associated metadata type” is, and why we need a type descriptor for working with it. Before going into those exact questions, we need to take a step back and examine the way some models are constructed.

We can all agree that the term “model” is pretty overloaded and has many different meanings/interpretations. You have domain models, presentation models, view models, super models, model trains, and so forth and so on. This series isn’t tied to any specific model implementation methodology per se, but rather on the intent of creating web applications that are focused around data in a RAD fashion. Because there are numerous ways of constructing an object model, we’d need a mechanism for discovering metadata from models that assume different shapes.

If you hand-craft your object model and perform the database-mapping yourself you could easily place data annotations on your entity classes and go on with it (as you might do if using NHibernate). While that is a totally valid scenario, it isn’t necessarily the right one for a data-driven application where you most likely already have a database in place and are looking to reverse engineer a model from it’s schema. For cases like that you might use something like LINQ To SQL or the Entity Framework, both of which provide designers/wizards for generating a mapped model to an existing database.

If I create a new Entity Data Model and point its wizard at an AdventureWorks database, I’ll end up with a whole bunch of generated entity classes that look something like this:

[global::System.Data.Objects.DataClasses.EdmEntityTypeAttribute(NamespaceName="AdventureWorks", Name="Address")]
[global::System.Runtime.Serialization.DataContractAttribute(IsReference=true)]
[global::System.Serializable()]
public partial class Address : global::System.Data.Objects.DataClasses.EntityObject
{
    ...
}

Because that class lives within the confines of my EDM, which is template-generated code, I don’t exactly want to go mucking around in there. If I later make a change with the designer, it would wipe out any changes I manually made to the entity classes, which would lead to a lot of pain and frustration. Luckily though, the entities are generated as partial classes which means we can make modifications to them from outside of the EDM’s code files. This gives us the ability to leverage the designer and still have some level of flexibility over the codebase moving forward.

I can easily create a new partial class for my Address entity and begin placing some data annotations on it. Let’s say that I want to specify that the display name for it should be “Customer Address” and that the column (property) that should be used to represent it’s display value should be “Country”. I could easily do this:

[DisplayColumn("Country")]
[DisplayName("Customer Address")]
public partial class Address
{
}

Because we’re using partial classes (which are combined at compile time), we’re still annotating the entity class itself, just using a different approach. We could easily retreive this metadata using standard reflection without requiring the need for a custom type descriptor. But what if I wanted to add metadata to one of the properties of my Address entity now? Let’s say that I wanted to specify that the Address2 property is required (even though it isn’t at the database level), PostalCode should be constrained by a regular expression, and that CountryRegion’s display name should just be “Country”. Because I don’t want to mess with the generated code of the EDM I can’t go place data annotations directly on those properties. I definitely can’t do the following, since that would be declaring the properties twice on the same class:

[DisplayColumn("Country")]
[DisplayName("Customer Address")]
public partial class Address
{
    public string Address2 { get; set; }
    public string CountryRegion { get; set; }
    public string PostalCode { get; set; }
}

It might seem like we’re out of luck at this point and have to settle with changing the generated EDM code. What if though, we could create a class whose sole purpose was to contain properties that we could annotate with metadata for another entity and then associate the two together? That would get us the functionality we need and work around the “issue” we’re dealing with between partial classes and generated code. Let’s say we created the following AddressMetadata class:

private class AddressMetaData
{
    public string Address2 { get; set; }
    public string CountryRegion { get; set; }
    public string PostalCode { get; set; }
}

We don’t get any compiler errors (obviously) so we’re moving in the right direction. How can we then associate this new type with our original Address entity class?

[MetadataType(typeof(AddressMetaData))]
public partial class Address
{

Now we can place any entity-level metadata on our Address partial class, and any property-level metadata on our new AddressMetaData class, because the two are associated. You can place/name your metadata type anywhere you want, but I prefer to make it a private/embedded class of the partial entity class itself. I can now add the metadata I want to my properties.

[DisplayColumn("Country")]
[DisplayName("Customer Address")]
[MetadataType(typeof(AddressMetaData))]
public partial class Address
{
    private class AddressMetaData
    {
        [Required]
        public object Address2 { get; set; }
 
        [DisplayName("Country")]
        public object CountryRegion { get; set; }
 
        [RegularExpression(@"\d{5}(-\d{4})?")]
        public object PostalCode { get; set; }
    }
}

Notice that I changed the type of the three properties to “object” because the property type no longer matters. Within the metadata type, we only need to be concerned with naming the property correctly.

We established that standard reflection could handle the discovery of the entity-level metadata, but now that we’ve create this “metadata type” which has its own set of properties and metadata, reflection would have no clue of its semantic association with the Address entity. This is where the AssociatedMetadataTypeTypeDescriptionProvider comes in.

The AssociatedMetadataTypeTypeDescriptionProvider class is capable of looking at a type and finding any of its class-level attributes as well as looking to see if that type has an associated metadata type (via the MetadataType attribute) and if it does, grabbing any metadata from the metadata type’s properties. This is a fairly roundabout approach, but it gets us around in the meantime. In the future you might see the notion of “partial properties” that would remove the need for the metadata type altogether.

So now it’s clear why the AssociatedMetadataTypeTypeDescriptionProvider exists and is the default behavior. If our model is able to apply all metadata directly to the entity classes, then it will work great. If our model requires the use of a “associated metadata type”, then it will also pick up on that as well. If we had an alternate style of model, that required a different type of metadata discovery, then we could implement a TypeDescriptionProvider and set it via the ContextConfiguration’s MetadataProviderFactory property. Dynamic Data uses the specified provider throughout its entire API, making it extremely easy to swap our your model metadata discovery logic.

Now that we’ve got our model created and we’ve begun adding metadata to it, how can we start seeing the fruits of our labor take effect within our web application’s UI? In the next article I’ll begin showing how Dynamic Data provides a set of extensions to ASP.NET that can take advantage of your annotated models and the MetaModels derived from them.

16
Dec

Dynamic Data: Annotating Your Data-Driven World

In the last article we discussed how a MetaModel could derive some of its metadata content from its respective provider’s underlying data model (i.e. an EDM), but also mentioned that there is a lot of valuable information that can’t necessarily be deduced from every data model type. Because a data model can come in any shape or form (i.e. EF, L2S, NHibernate, etc) it becomes tricky to try to interpret metadata in any sort of consistent fashion. Providers make an attempt at doing this, but really, their job isn’t to curry metadata back and forth between the MetaModel and underlying data model, but rather to shape the data model in such a way that the MetaModel can understand it.

Without a standard approach for adding metadata to data models (of any kind), data-driven UI frameworks would have a hard time providing the rich functionality we are demanding from them. By introducing the MetaModel, we’ve given the UI layer a robust view of the underlying data model such that it can provide the behavior we expect, so that problem is already solved. Now we just need a mechanism for annotating our model with metadata in such a way that our MetaModel can pick it up.

The .NET Framework 3.5 SP1 release contained an assembly named System.ComponentModel.DataAnnotations. Within that assembly is a collection of attributes that are meant to be associated with data models for the purpose of adding additional metadata and validation to them in a way that is agnostic to any specific UI framework. Notice that the namespace they live in isn’t “System.Web.*” or “System.Windows.*” but rather “System.ComponentModel.*”, which adds to the argument of standard use.

Because these data annotations are simply attributes, we can easily begin attaching them to our entity classes and properties, which adds additional information to our model such as validation constraints (range, regular expression, string length, etc.) and higher level semantics (data type, UI hint, scaffolding, etc.). The question is: how does our MetaModel discover these annotations once we’ve placed them on our model?

[DisplayColumn("FirstName", "LastName")]
public class Customer
{
    [Required]
    public string FirstName { get; set; }
 
    [StringLength(20)]
    public string MiddleName { get; set; }
 
    [Required]
    public string LastName { get; set; }
 
    [Range(18, 30)]
    public int Age { get; set; }
}

For any DDD proponents, I realize the above model class would be considered anemic. It’s important to keep in mind that the methodology being employed in this series is that of data-driven applications not domain-driven.

When you register a context/provider with a MetaModel (as we saw in a previous post), an instance of type ContextConfiguration is created and associated with your model. You can either explicitly create a ContextConfiguration instance and use one of the overloaded versions of the RegisterContext method that accepts one, or you can allow the MetaModel to create one for you. ContextConfiguration is an extremely simple class that contains only two properties: ScaffoldAllTables and MetadataProviderFactory. The ScaffoldAllTables property is only applicable if you’re leveraging Dynamic Data for full-blown scaffolding, which is a scenario we’ll touch on later.

// Implict ContextConfiguration...
var model = new MetaModel();
model.RegisterContext(typeof(AdventureWorksContext));
 
// Explicit ContextConfiguration...
var model2 = new MetaModel();
model2.RegisterContext(typeof(AdventureWorksContext),
                      new ContextConfiguration { ScaffoldAllTables = false });

The ScaffoldAllTables property defaults to false, so if we aren’t concerned with Dynamic Data’s scaffolding behavior (which in this case we aren’t), we can just omit that property instead of explicitly setting it.

The MetadataProviderFactory property is of type Func<Type, TypeDescriptionProvider>, which might look scarier than it actually is. Func is simply a generic delegate that returns a value and optionally takes up to four parameters (there are five variations of Func). In this case we’re dealing with a Func that will accept a parameter of type Type and return an object of type TypeDescriptionProvider. When we register a context/provider with a MetaModel, it will enumerate through every entity type in our model, calling the delegate within the ContextConfiguration’s MetadataProviderFactory property, which will then return an TypeDescriptionProvider.

model.RegisterContext(typeof(AdventureWorksContext),
                       new ContextConfiguration
                       {
                           MetadataProviderFactory = (type) => new CustomTypeProvider()
                       });

A TypeDescriptionProvider is (as you can probably guess) responsible for providing a type descriptor (more specifically an object that implements ICustomTypeDescriptor or inherits from CustomTypeDescriptor). An ICustomTypeDescriptor implementation is able to determine information about a type such as its properties, events, attributes, etc. This allows applications to use a type descriptor to retrieve metadata about a type instead of using reflection directly. Why is this useful? Because you could create a custom ICustomTypeDescriptor that represented the shape of a type differently then it is in code.

As was mentioned above, the standard data annotations are provided as attribute classes, so the fact that a type descriptor allows you to retrieve attributes from a type (as well as that type’s properties), makes it very useful. By being able to create a custom TypeDescriptionProvider we can effectively implement logic that retrieves our model metadata from any source (i.e. XML, database, etc.), but uses the same standard data annotations, giving us both consistency and flexibility.

If you don’t explicitly set the MetadataProviderFactory property, the Metamodel will internally create an instance of the AssociatedMetadataTypeTypeDescriptionProvider class (that is a hell of a name!). This TypeDescriptionProvider implementation simply retrieves all attributes for a type via reflection. Why is this any better than just using reflection directly? Because it also retrieves any attributes from the requested type’s associated metadata type as well.

What exactly does “associated metadata type” mean? And why is it beneficial that the TypeDescriptionProvider be able to retrieve its attributes? We’ll discuss these two questions and expand on the usage of data annotations in the next article.

10
Dec

Top 50 Albums of 2008 (…By "Top" I Mean "My Favorite")

I wasn’t going to do this post but I ended up not being able to sleep last night and decided “what the hell?”. I purposely did the list in no particular order as I feel that it isn’t realistic to quantify a specific placement of each album and have it mean anything. What exactly does the difference between #18 and #19 really look like? I spent many years writing for magazines and can attest to the fact that these lists are just subjective babble.

The majority of these albums are post-rock, electronic and instrumental artists. There are a few metal, indie, folk and post-hardcore albums as well. I did a TON of traveling this year and this is the collection that kept me sane around the world. If you care for a more “formal” list, you can check out my other site, The Silent Ballet, in a few weeks.

  1. Helios - “Ceasura” (Link)
  2. Lights Out Asia - “Eyes Like Brontide” (Link)
  3. Shearwater - “Rook” (Link)
  4. No.9 - “Usual Revolution And Nine” (Link)
  5. Sumner McKane - “What A Great Place To Be” (Link)
  6. Suffocate For Fuck Sake - “Blazing Fires And Helicopters On The Front Page Of The Newspaper. There’s A War Going On And I’m Marching In Heavy Boots” (Link)
  7. Bersarin Quartett - “Bersarin Quartett” (Link)
  8. This Town Needs Guns - “Animals” (Link)
  9. Jóhann Jóhannsson - “Fordlandia” (Link)
  10. Cult Of Luna - “Eternal Kingdom” (Link)
  11. This Is Your Captain Speaking - “Eternal Return” (Link)
  12. Up-C Down-C Left-C Right-C ABC + Start - “Embers” (Link)
  13. Balmorhea - “River Arms” (Link)
  14. Strangers Die Every Day - “Aperture For Departure” (Link)
  15. Takahiro Kido - “Fleursy Music” (Link)
  16. M83 - “Saturdays = Youth” (Link)
  17. Mouth Of The Architect - “Quietly” (Link)
  18. Lakes Of Russia - “Stars Decorate The Fire” (Link)
  19. Earth - “The Bees Made Honey In The Lion’s Skull” (Link)
  20. Fuck Buttons - “Street Horrrsing” (Link)
  21. The Drift - “Memory Drawings” (Link)
  22. Beneva Vs. Clark Nova - “Sombunall” (Link)
  23. Mooncake - “Langrange Points” (Link)
  24. We’re From Japan! - “Now Breath” (Link)
  25. The Evpatoria Report - “Maar” (Link)
  26. Arms & Sleepers - “Black Paris 86″ (Link)
  27. d_rradio - “d_rradio” (Link)
  28. Gregor Samsa - “Rest” (Link)
  29. Russian Circles - “Station” (Link)
  30. Ef - “I Am Responsible” (Link)
  31. Pg.Lost - “It’s Not Me, It’s You!” (Link)
  32. Neil On Impression - “L’oceano Delle Onde Che Restano Onde Per Sempre” (Link)
  33. He Can Jog - “Middlemarch” (Link)
  34. The Seven Mile Journey - “The Metamorphosis Project” (Link)
  35. Goodnight, Sleep Well - “The Recovery” (Link)
  36. Kyte - “Kyte” (Link)
  37. Unwed Sailor - “Little Wars” (Link)
  38. Daturah - “Reverie” (Link)
  39. Port Blue - “The Albatross” (Link)
  40. My Education - “Bad Vibrations” (Link)
  41. Build - “Build” (Link)
  42. God Is An Astronaut - “God Is An Astronaut” (Link)
  43. MGMT - “Oracular Spectacular” (Link)
  44. Lindstrøm - “Where You Go I Go Too” (Link)
  45. September Malevolence - “After This Darkness, There’s A Next” (Link)
  46. The Absent Sound - “Gathering Of The Clan Mothers” (Link)
  47. The Calm Blue Sea - “The Calm Blue Sea” (Link)
  48. Beast, Please Be Still! - “Beast, Please Be Still!” (Link)
  49. Robin Guthrie - “3:19 Bande Originale du Film” (Link)
  50. Peter Broderick - “Float” (Link)
21
Nov

Dynamic Data: The Little MetaModel That Could

When a MetaModel is initialized from a data source (via its respective provider), what additional information is determined in the process? The MetaModel itself contains a couple of useful instance properties and methods (more of which we’ll examine later), but for the purpose of this article, we only care about its Tables property, which is of type ReadOnlyCollection<MetaTable>. As you can imagine, that property returns a list of MetaTable instances that represent every entity in our underlying data source.

The MetaTable class contains a whole slew of useful properties that we otherwise couldn’t deduce from its respective model class, such as: ForeignKeyColumnNames, DisplayName, PrimaryKeyColumnNames and SortColumn. As you can see, because of the higher-level semantics provided us by the MetaModel, any controls within our UI, that are aware of the MetaModel, can now take advantage of these additional attributes. The MetaTable class also contains a Columns property, which is of type ReadOnlyCollection<MetaColumn>, and contains a list of every column/property in the entity.

The MetaColumn class is where the real meat of the metadata system lies. It contains loads of properties for gathering information about a column/property from its underlying model, such as: DefaultValue, IsGenerated, IsRequired, MaxLength, NullDisplayText and RequiredErrorMessage. In addition, a MetaColumn can be of type MetaChildColumn or MetaForeignKeyColumn if it participates in an association.

Why does any of this matter? Because this rich MetaModel, in conjunction with our actual data model, provides us with enough information about the structure/semantics of the data that we can begin deducing lots of functionality/behavior from it. Better yet, our UI can do that for us. It’s clear at this point that the only thing we need in order to begin developing smarter data-centric applications are UI frameworks that can understand and react to the contents of our MetaModel.

Before we move on to examining how Dynamic Data provides extensions to ASP.NET that allow our UI to make use of a MetaModel, we need to briefly address where the MetaModel is getting its contents from. How exactly does it know what the DefaultValue for a column is, or the DisplayName for an entity is? It simply asks the provider. If you’re using an Entity Data Model, its respective provider can scavenge metadata from the EDM; if you’re using a LINQ To SQL model, its respective provider can examine the MetaModel (yes L2S uses this term as well) for metadata; if you’re using any other datasource, then you can create a custom provider that can determine that information however it makes sense.

You may be thinking right now that neither an EDM nor a L2S model provide the full extent of metadata that I’ve highlighted our MetaModel as exposing, and you’d be exactly right. In addition to the providers looking at their datasource specific mediums for metadata, there is also a set of common data annotations that can be applied to your data model and will be picked up by the MetaModel. These annotations live in the System.ComponentModel.DataAnnotations assembly/namespace.

These annotations have absolutely nothing to do with Dynamic Data, and are meant solely for annotating model classes within data-driven applications. Dynamic Data just happens to be the first UI framework (technically ASP.NET is) that understands them and makes use of them. In the next article I’ll explain how to make use of these annotations.

19
Nov

Dynamic Data: Models, MetaModels And Everything In Between

In the previous article, I mentioned that the existing data controls in WebForms aren’t very smart as regards to your data, but in all fairness, it isn’t really their fault. How is a GridView supposed to know that a property is required? How can a FormView know that a specific control should include regular expression validation? How can a DetailsView know that certain columns shouldn’t be displayed? Since those controls are completely agnostic as to the type of data they are bound to, there is no set of common assumptions they can make about their bound data in order to provide a richer set of UI behaviors.

It almost seems like what we need is some sort of meta-model, that provides additional semantics/metadata on top of our data model that our WebForms controls can leverage to make the desired assumptions. That way, we could bind any type of data to the controls, and they wouldn’t have to rely on any specific model type, but could rather use the meta-model to determine the additional actions it should (or shouldn’t) take. Because the meta-model would have a common form, the controls would only have to be aware of a single metadata system.

While having a common metadata representation is great, how can a meta-model be created based on every possible type of data? Obviously that wouldn’t be practical to have a single codebase that determined metadata from every data type. Rather, what we’d need is the ability to create a provider that was aware of a specific data type and could create a meta-model from it. This way, allowing a new data type to work with our common metadata system would be as easy as creating a new provider.

The solution described thus far is exactly what Dynamic Data provides. A common meta-model system for describing data models with a higher semantic that a UI can leverage to be smarter by default. Out of the box, it includes providers for LINQ-To-SQL and the Entity Framework (which is why it has gotten a reputation for working solely against databases), but nothing stops it from working against any other data source. In fact, prototypes already exist that have Dynamic Data working against an ADO.NET Data Service, as well as a SQL Data Service.

So what does the code look like for creating a meta-model from an existing data model?

public class Global : HttpApplication
{
    protected void Application_Start(object sender, EventArgs e)
    {
        var model = new MetaModel();
        model.RegisterContext(typeof(AdventureWorksContext));
    }
}

In that code sample, “AdventureWorksContext” is the name of my ObjectContext (a generated class used for working with an Entity Data Model). It could have also been a DataContext (a class used for working with a LINQ To SQL model), and the MetaModel would have been created just fine. This is because the RegisterContext method is aware of L2S and EF models and will created the necessary provider to fill the MetaModel. What if your data source is something other then a L2S or EF model? Then you can just pass an instance of your custom provider to the RegisterContext method.

var model = new MetaModel();
model.RegisterContext(new ArbitraryDataModelProvider());

Your provider would then be responsible for traversing your data source and retrieving the metadata that described it. The first MetaModel that you create is considered the default instance, and is stored in the static MetaModel.Default property. MetaModels can also be retreived by type using the MetaModel.GetModel method (in case you have multiple). Once you’ve created your MetaModel during your application’s start event in the Global.asax file, your MetaModel is now globally available throughout your application, just waiting to be leveraged by your UI.

While this all seems dandy, two questions arise: what metadata does the MetaModel expose, and where did it get it from? I’ll cover those questions in the next article.