Yesterday, I gave a talk on ASP.NET Dynamic Data at the MIX 2008 conference.  It was a full room, and it was great to see the interest for the technology.  What's nice about MIX is that they are making all talks available online within 24 hours.  So you can watch my talk today!  Here is the direct link.

Note that the build of Dynamic Data that I use in the session is quite a bit newer than the one we made available in December.  You should expect the new build to be available within a few weeks.

While a lot of the core concepts remain the same, there are a number of important changes, and I'll describe some of them here:

 

Entity Framework support

In addition the Linq To Sql, Dynamic Data now supports Entity Framework.  For the most part, everything works the same way.  When you get started, you create an Entity Framework model instead of a Linq To Sql model.  You'll also notice that pages use an EntityDataSource instead of a LinqDataSource.  This is a new data source control from the Entity Framework team, and it will be usable both in Dynamic Data apps and in 'regular' ASP.NET pages.

 

Folder structure changes

In the December CTP, we were using an App_Shared folder, and that name really didn't make much sense.  The new folder structure uses name that better describe the semantic.  Here is what it looks like

  • App root
    • global.asax, web.config, site.master, ...
    • DynamicData
        • PageTemplates
          • list.aspx, details.aspx, edit.aspx, insert.aspx
        • CustomPages
          • SomeTable
            • list.aspx, details.aspx, edit.aspx, insert.aspx
          • SomeOtherTable
            • list.aspx, details.aspx, edit.aspx, insert.aspx
        • FieldTemplates
          • boolean.ascx, integer.ascx, etc...

 

Use of ASP.NET Routing to configure URLs

In the CTP, Dynamic Data was using a fairly complex web.config section to customize its URLs.  Unfortunately, it was a bit hard to use, and not as customizable as it needed to be.  Instead, we are now using the new ASP.NET Routing feature.  See this post from Scott Guthrie for an  introduction to the feature.  Also, check out my MIX Session video for examples of how this works in Dynamic Data (around 42 minutes into it).

In a nutshell, routing allows you to decouple your external URLs from the internal structure of your web files.  That means that you can change the URLs that your users see in the web browser without having to move your files around accordingly.  It's a bit of a mind shift when you're used to URLs mapping directly to a server file, but it's a pretty powerful concept once you get used to it.

 

Here is an example of what a custom route may look like in a Dynamic Data app.  This code typically lives in your Application_Start (in global.asax).

RouteTable.Routes.Add(new DynamicDataRoute("Hello/{action}/DynamicData/{table}") {
    Constraints = new RouteValueDictionary(new { action = "Edit|Insert" }),
    Model = model
});

 

Direct support for GridView, DetailsView and other data controls

In the December CTP, you had to use new versions of those controls, like DynamicGridView.  To avoid the proliferation of new controls, we now support directly using the existing data controls in Dynamic Data web sites.

 

Changes to the way metadata attributes are specified on the model

We have changed the way you specify metadata on your model properties.  Previously, everything was done at the class level.  Now, we use a 'buddy' class that can hold the metadata at the property level.  Here is an example:

[MetadataType(typeof(Product_MD))]
public partial class Product {
    partial void OnProductNameChanging(string value) {
        if (value[0] == 'a')
            throw new Exception("Must not start with a");
    }
}

public class Product_MD {
    [DisplayName("My units")]
    [Description("This number shows how many unites are left")]
    [Range(0, 150, ErrorMessage = "Incorrect range for the units in stock")]
    [UIHint("IntegerSlider")]
    public object UnitsInStock { get; set; }

    [UIHint("BooleanAjax")]
    public object Discontinued { get; set; }
}

If you're wondering why we need an extra class, the reason is that there is no way in C# (and VB) to add attributes to properties defined on the other side of the partial class (which is the generated model file).  Still, this is an improvement over having all the attributes for all the properties specified at class level.  We're hoping that future language improvement will allow us to remove the need for the extra class.

Note that the metadata model is extensible via standard TypeDescriptionProviders.  The 'buddy' class mechanism shown above is the default provider that comes with Dynamic Data, but you can write new providers that get their data from arbitrary other places: XML file, database, ...

 

Model registration and support for multiple models

In the CTP, the model was registered in web.config, and only a single model was supported.  Now, the registration happens in your Application_Start (in global.asax), next to where you have your routes.  Here is what a typical registration looks like:

MetaModel model = new MetaModel();
model.RegisterContext(typeof(NWDataContext), new ContextConfiguration() { ScaffoldAllTables = true });

You could register multiple models, and would pass the relevant one to each route (see route example above).  Also note that 'ScaffoldAllTables' attribute.  By default it's false.  Making it true turns on scaffolding for that model, mean that the tables are made available via the page templates.  When it's false, only custom pages (living under DynamicData\CustomPages) are supported.

 

New extensibility points for Page Templates and Field Templates

You can  now customize many aspects of how field and page templates work.  Things you can customize include:

  • The location of the folders containing the templates
  • How templates are selected
  • You can completely override the field template creation process, which for example lets use use precompiled controls instead of user controls (ascx files).

 

Many bug fixes and API renames

We fixed a lot of issues, and cleaned up a lot of API names to be more straightforward and discoverable.