ASP.NET Dynamic Data - Simple 5 Table Northwind Example

I have been anxiously awaiting the Dynamic Data release.  And now that it is here (it was released with VS 2008 and .Net 3.5 SP1) I decided I would start getting a feel for what is has to offer by building a real simple Dynamic Data web site that allows you to browse the 5 core Northwind tables - Customers, Employees, Orders, Products and Suppliers.  Read on for the details and don't forget to download the codeDiscountASP hasn't quite upgraded to SP1 so I don't have a live demo setup.  Hopefully they will get the upgrade completed soon, but I made sure to include lots of screen shots so you can get a good idea of what the screens look like. 

[Update 9/21/2008] : Add link to the live demo

Download | Live Demo

image

 

What is Dynamic Data?

I try to keep a close eye on ASP.NET, but I didn't know Dynamic Data was shipping as part of SP1.  I asked around the office and found out this took a few other people by surprise too.  And more than a few people had actually never heard of Dynamic Data.  In case you fall into that category, here are a couple of quotes that describe what DynamicData is all about.

From Wikipedia ...

ASP.NET Dynamic Data is a web application scaffolding framework from Microsoft, shipped as an extension to ASP.NET, that can be used to build data driven web applications. It exposes tables in a database by encoding it in the URI of the ASP.NET web service, and the data in the table is automatically rendered to HTML. The process of rendering can be controlled using custom design templates. Internally, it discovers the database schema by using the database metadata.

From asp.net ...

ASP.NET Dynamic Data provides a framework that enables you to quickly build a functional data-driven application, based on a LINQ to SQL or Entity Framework data model. It also adds great flexibility and functionality to the DetailsView, FormView, GridView, and ListView controls in the form of smart validation and the ability to easily change the display of these controls using templates.

 

So for this demo app, I am planning on using Dynamic Data to build a web application that allows me to browse the Northwind database.

 

Create the Dynamic Data Web Site

To get started building a Dynamic Data Web Site, you do the usual File -> New -> Web Site and select either the Dynamic Data Entities Web Site or Dynamic Data Web Site templates.  If you plan on using the ADO.NET Entity Framework for data access you can select the first option, otherwise if you are using LINQ to SQL you select the second template.  For this example I am using LINQ to SQL so I chose the Dynamic Data Web Site template.

image

 

When VS finishes loading, you will notice a number of files/folders have been included in the solution.  The solution includes a DynamicData folder that is filled with other folders and each is filled with both UserControls and regular ASP.NET Pages.

image

Create and Register the LINQ to SQL DataContext

I am going to use LINQ to SQL to access the my Northwind data, so I used the VS designer create the LINQ to SQL classes for the tables I want by dragging my tables over from the server explorer and dropping them onto the design surface.

image 

 

After creating the DataContext, I update the Global.asax and register my NorthwindDataContext with the DynamicData system.  The web site template generates the code that handles all of this, you just have to read the comments and plug in your custom context type.  Here is what it ends up looking like ...

   1: public static void RegisterRoutes(RouteCollection routes) {
   2:     MetaModel model = new MetaModel();
   3:     
   4:     //                    IMPORTANT: DATA MODEL REGISTRATION 
   5:     // Uncomment this line to register LINQ to SQL classes or an ADO.NET Entity Data
   6:     // model for ASP.NET Dynamic Data. Set ScaffoldAllTables = true only if you are sure 
   7:     // that you want all tables in the data model to support a scaffold (i.e. templates) 
   8:     // view. To control scaffolding for individual tables, create a partial class for 
   9:     // the table and apply the [Scaffold(true)] attribute to the partial class.
  10:     // Note: Make sure that you change "YourDataContextType" to the name of the data context
  11:     // class in your application.
  12:     model.RegisterContext(typeof(NorthwindDataContext), new ContextConfiguration() { ScaffoldAllTables = true });
  13:  
  14:     // The following statement supports separate-page mode, where the List, Detail, Insert, and 
  15:     // Update tasks are performed by using separate pages. To enable this mode, uncomment the following 
  16:     // route definition, and comment out the route definitions in the combined-page mode section that follows.
  17:     routes.Add(new DynamicDataRoute("{table}/{action}.aspx") {
  18:         Constraints = new RouteValueDictionary(new { action = "List|Details|Edit|Insert" }),
  19:         Model = model
  20:     });
  21:  
  22:     // The following statements support combined-page mode, where the List, Detail, Insert, and
  23:     // Update tasks are performed by using the same page. To enable this mode, uncomment the
  24:     // following routes and comment out the route definition in the separate-page mode section above.
  25:     //routes.Add(new DynamicDataRoute("{table}/ListDetails.aspx") {
  26:     //    Action = PageAction.List,
  27:     //    ViewName = "ListDetails",
  28:     //    Model = model
  29:     //});
  30:  
  31:     //routes.Add(new DynamicDataRoute("{table}/ListDetails.aspx") {
  32:     //    Action = PageAction.Details,
  33:     //    ViewName = "ListDetails",
  34:     //    Model = model
  35:     //});
  36: }

 

And really after you have done this you have a pretty nice looking and functional web site.  A landing page that lets you know about what tables are available ...

image

 

Grids for viewing the contents of these tables (paging and sorting included) ...

image

And pages for Inserting, Updating and viewing Details ...

image

 

Customization

If I was happy with how all of the default pages look, I could have stopped here and had a functional web application that supports basic CRUD operations.  That's pretty cool.  And that took all of what ... 5 minutes?  But what if I would like to change a few things?

 

Customizing the List Page Template

The List template is located in the DynamicData/PageTemplates folder.  The default List page look pretty good, but I wanted to see what it would take to make a few changes.  So I opened the List.aspx page and started making my changes. 

  • First, I added a black border by wrapping the GrdView in a series of DIVs that use background images to style the border. 
  • Next, I increased the PageSize from 10 to 15.
  • Then added a different Data Pager
  • Finally, I want my site to be read-only so I removed the Insert, Edit and Delete links

 

Nothing too major, but styles provide quite a bit of change.

image

 

Customizing the Details Page Template

Next, I made similar changes to the Details page template.

 image

Adding Custom Metadata to the Model

There are a few things that you will notice in the screen shots above with my custom pages that are different from the default pages.

  • The grids column counts are different (my custom pages have fewer columns) 
  • Some of the column headers have different names
  • Some of the grid's cell values are formatted differently
  • The display name for the table

 

To customize these items, you need to create a metadata class that provides Dynamic Data with a little more information about your entities.  I will be honest, this part seems a little weird to me, but that might just be because it is new.  Anyway, to accomplish this you need to create two more classes for each of the classes in your DataContext.  So for my 5 table sample, I need to create 10 more classes to attach my metadata. 

First you add a partial class with the same name of the entity class in the data model and then apply an attribute to this partial class that ties it to the additional metadata we have defined for the class.  The code snippet below is what does this for the Order entity in our sample application.  The following bit of code tells Dynamic Data the following ...

  • The display name for the Order table is 'My Orders' - Applied with the TableName attributes
  • The OrderDate, ShippedDate, ShipAddress and ShipCity columns all have overridden display names - Applied with the DisplayName attribute
  • The OrderDate and ShippedDate columns have a custom format - Applied with the DisplayFormat attribute
  • The RequiredDate, ShipVia, Freight, ShipName, ShipPostalCode, and ShipCountry columns should be hidden from the UI - Applied with the ScaffoldColumn attribute
   1: //  Attach the OrderMetadata to the Order class
   2: [MetadataType(typeof(OrderMetadata))]
   3: public partial class Order {}
   4:  
   5: [TableName("My Orders")]
   6: public class OrderMetadata
   7: {
   8:     //  Override the display name
   9:     [DisplayName("Date Ordered")]
  10:     //  Format the Date
  11:     [DisplayFormat(DataFormatString="{0:d}")]
  12:     public object OrderDate { get; set; }
  13:     //  Override the display name
  14:     [DisplayName("Date Shipped")]
  15:     //  Format the Date
  16:     [DisplayFormat(DataFormatString = "{0:d}")]
  17:     public object ShippedDate { get; set; }
  18:     //  Override the display name
  19:     [DisplayName("Address")]
  20:     public object ShipAddress { get; set; }
  21:     //  Override the display name
  22:     [DisplayName("City")]
  23:     public object ShipCity { get; set; }
  24:  
  25:     //  Columns I want hidden
  26:     [ScaffoldColumn(false)]
  27:     public object RequiredDate { get; set; }
  28:     [ScaffoldColumn(false)]
  29:     public object ShipVia { get; set; }
  30:     [ScaffoldColumn(false)]
  31:     public object Freight { get; set; }
  32:     [ScaffoldColumn(false)]
  33:     public object ShipName { get; set; }
  34:     [ScaffoldColumn(false)]
  35:     public object ShipPostalCode { get; set; }
  36:     [ScaffoldColumn(false)]
  37:     public object ShipCountry { get; set; }
  38: }

 

 

Conclusion

Well that was my first pass through building a Dynamic Data site.  I am pretty impressed and I am looking forward to exploring this further - stay tuned.

 

That's it.  Enjoy!


TrackBack

TrackBack URL for this entry:
http://mattberseth.com/blog-mt/mt-tb.fcgi/147

Listed below are links to weblogs that reference ASP.NET Dynamic Data - Simple 5 Table Northwind Example:

» ASP.NET Dynamic Data - Simple 5 Table Northwind Example from DotNetKicks.com
You've been kicked (a good thing) - Trackback from DotNetKicks.com [Read More]

» Grids Links from iLinkShare (Web 2.0 linksharing)
Tagged your site as grids at iLinkShare! [Read More]

Comments


Very good introduction Matt. Good point you covered with UI Customization and changing display labels of columns. Really good start for you and for us.

Thanks Matt, I have used Dynamic Data before, but I'm sure I will be referring back to your summary here quite often as I dig deeper into it in future projects.

One issue I haven't figured out is how to integrate this into a project. In the one project I used this on, I basically made an entirely separate site on a subdomain (data.xyz.com) for the users to go in and manage the data.

It seems like it would be a bit of work to integrate Dynamic Data functionality into an existing project...

Posted by: DaCoder on August 21, 2008 03:09 PM

Thanks a lot Matt, for this timely article. This should give ROR folks a run for their money.

I think its a step in the right direction for sure.

Another great thing about this is it does work with LLBLGen.

http://bryan.reynoldslive.com/post/LLBLGen-Pro-and-Microsoftrsquo3bs-Dynamic-Data-to-play-nice!.aspx

This is an excellent walk-through. Thanks for sharing this.
-Ryan

Posted by: Anonymous on August 22, 2008 01:23 PM

I didn't see a live demo. So, I must ask. Is this AJAX based, or is it based purely on server controls that require postback?

I have been playing with jqGrid 3.2 (jQuery Grid) and I have to say I'm a bit more impressed with it at the moment. While it is not drag and drop, writing the markup and underlying CRUD (ASP.NET web services) is straight forward.

Unless the ASP.NET/ASP.NET AJAX frameworks start including some client-side controls for data manipulation, they won't offer the experience that most people are looking for.

Posted by: Stephen on August 22, 2008 01:24 PM

I didn't see a live demo available. So, I must ask. Is this AJAX based, or is it based purely on server controls that require postback?

I have been playing with jqGrid 3.2 (jQuery Grid) and I have to say I'm a bit more impressed with it at the moment. While it is not drag and drop, writing the markup and underlying CRUD (ASP.NET web services) is straight forward.

Unless the ASP.NET/ASP.NET AJAX frameworks start including some client-side controls for data manipulation, they won't offer the experience that most people are looking for.

Sorry for the repost ... my last comment didn't have my name.

Posted by: Joshua on August 22, 2008 03:46 PM

Pretty sleek. How is this compared to Subsonic's scaffolding?

Posted by: roger pence on August 24, 2008 10:06 PM

Matt--

Your blog is great. Thanks for such great content. Here's a question that's a little off topic--can you tell us a little about your hosting plan with DiscountASP.NET. What plan are you using? Got any horror stories or recommendations about hosing an active blog (your active online examples are great!)?

Thanks
rp

Hello Matt-

How would one go about controlling the display of a field so that it is Visible, but at the same time the field is not Editable?

For example, most of our maintenance tables contain a last changed User stamp and Time stamp field. These fields should be visible in the List.aspx, but not editable in the Edit.aspx. (We'd programmatically set them behind-the-scenes upon Edit).

How could you accomplish this using the MetaTable? My initial experiments seemed to indicate if a field was Scaffold'ed as hidden, it wasn't sent to the database on update at all (therefore any custom get/set didn't really apply).

Thanks for the great post-

I was searching for "simple table maintenance asp.net sample" and this came up. Just what I was looking for. Great post.

Thanks!

Post a comment

(If you haven't left a comment here before, you may need to be approved by the site owner before your comment will appear. Until then, it won't appear on the entry. Thanks for waiting.)

Consulting Services

Yep - I also offer consulting services. And heck, I'll do just about anything. If you enjoy my blog just drop me an email describing the work you need done.

Recent Comments

  • Patrick wrote: I was searching for "simple table maintenance asp.net sample" and this came up. Just what I was look...
  • Kenneth Scott wrote: Hello Matt- How would one go about controlling the display of a field so that it is Visible, but at...
  • roger pence wrote: Matt-- Your blog is great. Thanks for such great content. Here's a question that's a little off top...
  • Joshua wrote: Pretty sleek. How is this compared to Subsonic's scaffolding?...
  • Stephen wrote: I didn't see a live demo available. So, I must ask. Is this AJAX based, or is it based purely on s...
  • wrote: I didn't see a live demo. So, I must ask. Is this AJAX based, or is it based purely on server cont...
  • Ryan Farley wrote: This is an excellent walk-through. Thanks for sharing this. -Ryan...
  • Bryan Reynolds wrote: I think its a step in the right direction for sure. Another great thing about this is it does work ...