Using Dynamic Data Controls In Your Existing Project

by bigcarlito Tuesday, October 07, 2008

Just about every site I've ever created has needed some screens to manage the data in certain tables - whether it's users, products, or in my most recent case forums.  I always overlook the time it takes to make a basic CRUD (CReate-Update-Delete) screen. 

There really is a lot of work that goes into these types of screens: Get the data, hook the data up to a grid, format the grid and the fields in the grid, create a details view, format the details view and the detail fields, hook the details view up to the grid, enable editing of the fields, validate the inputs on save, save or insert the data, refresh the grid after saving, and on and on it goes.  PHEW! 

"Uh, excuse me Mr. Project Manager, how long did I estimate for this task again?" :-) 

Dynamic Data To The Rescue

After installing Visual Studio 2008 SP1, you may have noticed a new web application project called Dynamic Data Web Application.  A Dynamic Data web application provides a framework for quickly and easily creating CRUD screens for any tables in your database.

However, an entire web application dedicated to managing the data in a database is not very practical.  In a typical software project, whatever CRUD screens you need are usually just a small piece of the entire application.

The good news is that Dynamic Data is fairly easily integrated into your existing projects as well.  Props to Scott Hanselman for explaining clearly how to do this

So here's a summary of exactly how I went about adding screens for managing the Forums table in my existing application:

Step 1: Add Dynamic Data To Your Project

There are a few specific things you'll need to do to add Dynamic Data to your Web Forms or MVC project:

I. Add a reference to System.Web.DynamicData 

II. Add dynamic data controls to the <controls> element of your web.config

<pages>
    <controls>
        <add tagPrefix="asp" namespace="System.Web.DynamicData" 
assembly="System.Web.DynamicData, Version=3.5.0.0, 
Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>  
    </controls>
 

III.  Register your model in Global.asax

protected void Application_Start()
{
   MetaModel model = new MetaModel(); 
   model.RegisterContext(typeof(SocialDataContext), 
new ContextConfiguration() { ScaffoldAllTables = false });
   RegisterRoutes(RouteTable.Routes);
}

IV.  Add the DynamicData folder and contents to your project

As suggested by Scott H., the best way to do this is to go create a brand new Dynamic Data Web Application project off in another directory.  Be sure to name the new project the exact same name as your current project so namespaces will all match up.  Once created, copy the DynamicData folder and all it's contents over to your project directory and include the entire thing in your project.

 

Step 2: Create A Web Form and add a DynamicDataManager

Pretty simple, create your web form and and add the DynamicDataManager control to it:

<asp:DynamicDataManager ID="DynamicDataManager1" runat="server" />  

Step 3: Add A GridView

Next step is to add a grid that will contain the table data. The only really interesting part here is the columns of the gridview - they are controls of type DynamicControl. These smart controls look at the type of data they are given and automatically determine the best way to display it:

<!-- The Data -->
<asp:LinqDataSource ID="DataSourceItems" runat="server" 
ContextTypeName="Social.Models.SocialDataContext" EnableDelete="True" 
EnableInsert="True" EnableUpdate="True" TableName="Forums" 
OrderBy="DisplayOrder, ForumName">
</asp:LinqDataSource>
<!-- The Grid -->
<asp:GridView ID="gvItems" runat="server" AllowPaging="True" AllowSorting="True" 
AutoGenerateColumns="False" DataSourceID="DataSourceItems" 
onselectedindexchanged="gvItems_SelectedIndexChanged">
<Columns>
<asp:CommandField ShowSelectButton="True" HeaderStyle-Width="60" />
<asp:TemplateField HeaderText="Forum" SortExpression="ForumName">
<ItemTemplate>
<asp:DynamicControl ID="DynamicControl1" runat="server" DataField="ForumName" />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Category" SortExpression="ForumCategory.ForumCategory1">
<ItemTemplate>
<asp:DynamicControl ID="DynamicControl2" runat="server" DataField="ForumCategory" />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Sort" SortExpression="DisplayOrder">
<ItemTemplate>
<asp:DynamicControl ID="DynamicControl3" runat="server" DataField="DisplayOrder" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
<!-- An 'Add New' Button -->
<div class="addrow">
<asp:LinkButton ID="btnInsert" runat="server" onclick="btnInsert_Click">Add New
</asp:LinkButton>
</div>

Step 4: Add The Details View

Next up we'll add the details view where the user will be able to update any editable properties of the selected item or add a new item.  Again the interesting part (and the part you'll change when you make your own page) are the DetailsView columns.

The DynamicField controls peek at the datatype of the field they are bound to and provide the appropriate input control for that datatype.  Not only that, but validation is built in as well!  Pretty neat, eh?

<!-- Details -->
<asp:Panel ID="PanelDetails" runat="server" Visible="false">
<!-- Input Fields -->
<asp:DetailsView ID="dvItem" runat="server" 
AutoGenerateRows="False" DataKeyNames="ForumID" DataSourceID="DataSourceDetails" 
AutoGenerateDeleteButton="True" AutoGenerateEditButton="True" 
AutoGenerateInsertButton="True" onitemdeleted="dvItem_ItemDeleted" 
onitemupdated="dvItem_ItemUpdated" oniteminserted="dvItem_ItemInserted"> 
<Fields>
<asp:DynamicField DataField="ForumID" HeaderStyle-Width="150" HeaderText="Forum ID:" />
<asp:DynamicField DataField="ForumName" HeaderText="Forum Name:" />
<asp:DynamicField DataField="ForumDesc" HeaderText="Description:" />
<asp:DynamicField DataField="DisplayOrder" HeaderText="Sort:" />
<asp:DynamicField DataField="ForumCategory" HeaderText="Category:" />
<asp:DynamicField DataField="IsPrivate" HeaderText="Private:" />
<asp:DynamicField DataField="ParentForum" HeaderText="Parent:" />
</Fields>
</asp:DetailsView>
<!-- Details DataSource -->
<asp:LinqDataSource ID="DataSourceDetails" runat="server" 
ContextTypeName="Social.Models.SocialDataContext" EnableDelete="True" 
EnableInsert="True" EnableUpdate="True" TableName="Forums" 
Where="ForumID == @ForumID">
<WhereParameters>
<asp:ControlParameter ControlID="gvItems" DefaultValue="-1" Name="ForumID" 
PropertyName="SelectedValue" Type="Int32" />
</WhereParameters>
</asp:LinqDataSource>
</asp:Panel> 

In software development, it often is all the little things that take up the most time.  The old saying 'the last 20% is 80% of the work' certainly is true in my experience.  Dynamic Data is a huge timesaver in that regard, it handles all the little details of a common but typically painstaking task.

Step 5: Handle A Few Events

Finally, in the code behind, we'll handle a few of the events to make the flow of work a little smoother.  Notice how little code is required to make this fully featured CRUD screen:

    protected void Page_Load(object sender, EventArgs e)
    {
      DynamicDataManager1.RegisterControl(gvItems);
      DynamicDataManager1.RegisterControl(dvItem);
    }
    protected void gvItems_SelectedIndexChanged(object sender, EventArgs e)
    {
      PanelDetails.Visible = true;
    }
    protected void btnInsert_Click(object sender, EventArgs e)
    {
      dvItem.ChangeMode(DetailsViewMode.Insert);
      PanelDetails.Visible = true;
    }
    protected void dvItem_ItemInserted(object sender, DetailsViewInsertedEventArgs e)
    {
      RefreshGrid();
    }
    protected void dvItem_ItemDeleted(object sender, DetailsViewDeletedEventArgs e)
    {
      RefreshGrid();
    }
    protected void dvItem_ItemUpdated(object sender, DetailsViewUpdatedEventArgs e)
    {
      RefreshGrid();
    }
    private void RefreshGrid()
    {
      gvItems.DataBind();
      gvItems.SelectedIndex = -1;
    }

So How Do I Use This?

For anyone wanting to use this, here's what you need to change to suit your situation:

  1.  Edit the grid's datasource to pull data from your table in your DataContext
  2.  Update the grid's columns - most importantly the DataField properties - to match the fieldnames (or in this case LINQ properties) from your table
  3.  Update the details datasource pull the specific record from your table based on the key field from grid
  4.  Update the details view to include all the columns that cannot be null or that you want to be editable by the user

That's it!  Pretty much everything else is handeled through the magic of Dynamic Data!

A Dynamic Data app also comes with a lot of scaffolding for mapping URLs to tables and dynamically generating entire CRUD pages.  The purpose of this post was simply to show how to use the Dynamic Data controls in your existing projects with minimal changes to how the rest of your project does things. Hope it was helpful!
Share/Save/Bookmark     kick it on DotNetKicks.com

Comments

DotNetKicks.com

10/12/2008 9:13:53 PM

trackback

Trackback from DotNetKicks.com

Using Dynamic Data Controls In Your Existing Project

Comments are closed