Practical ASP.NET

Deferring Data Retrieval in Master/Detail Pages

This is one big problem that's simple to fix. Peter shows you two solutions.

It's easy to create master/detail pages in ASP.NET. But it's equally easy to reduce your application's scalability if you implement your page naively.

When it comes to displaying data on the page, the Holy Grail that everyone seems to want is the master/detail page: a GridView or DropDownList at the top of the page that displays a list of choices (the "master") and a DataView or FormView at the bottom of the page that, when a record is selected in the master control, displays all the related records (the "detail"). Unfortunately, most developers implement this design in a way that reduces their application's scalability.

The problem occurs because the Page, by default, always selects a record in the master control. As a result, a naive implementation of a master/detail page results in the details for the first record on the Page being displayed when the page is first requested -- before the user has had a chance to pick a record in the master.

The naive implementation violates the first rule of scalability: Until you know what data your user wants, you should never (never!) retrieve any data. Retrieving data involves the two slowest things your application can do: reading from the hard disk and making a call to an external computer -- in this case, the database server. Unless all of your users always want to see the detail information for the first item in the master, the naive master/details design ensures a useless trip to the database.

And it's so easy to fix.

Delaying Data Retrieval
The reason that the details are retrieved is that the Page automatically calls the DataBind method of all DataViews on the Page. Calling the DataBind method of the master control fills the control with data and causes the first record in the control to be selected. The Page then goes on to call the DataBind method on the child control and the child control retrieves the details for the first record in the master control.

There are two solutions to this problem. The first is to configure your child DataView and DataSource at design time as before but then set the child DataView's DataSourceID property to null. This effectively disconnects the DataView from its DataSource. The Page skips over any DataViews with a null DataSourceID, so no detail data is retrieved.

The next step in this solution is to add code so that when the user makes a selection in the master control, the child's DataSourceID and DataSource are "re-wired." The simplest solution is to put code behind a search button that sets the child's DataSourceID to its related DataSource and then calls the child's DataBind method (you could put the code in the master control's SelectedItemChanged event but that makes it difficult for the user to retrieve the first record in the master control). This is probably the best solution when the master control is a GridView.

If the master control is a DropDownList or some other listing control, another solution is to load a dummy item into the master control at design time (typically, this item has a Text value of "Select a Customer" or the like). You need to set the listing control's AppendDataBoundItems property to True to ensure that the item you added at design time won't be wiped out when the listing control's DataBind method is called.

Some code is still required: In the control's Selecting event (fired just before data is retrieved), you need to check for the design time entry and cancel the retrieval:

 If e.Command.Parameters(0).Value = "Select a Customer" Then
  e.Cancel = True
  End If

There are more complicated solutions. I've seen developers have their users enter their selection criteria on one page and then transfer those criteria in a querystring to the page that displays the detail data. This ensures that the user's selection is known when the detail page first displays.

Unfortunately, this design either requires the user to return to the first page to enter new criteria or requires the developer to duplicate the master control on both pages. It's simpler to put the whole design on one page and defer retrieving data until after the users have made their selection.

About the Author

Peter Vogel is a system architect and principal in PH&V Information Services. PH&V provides full-stack consulting from UX design through object modeling to database design. Peter tweets about his VSM columns with the hashtag #vogelarticles. His blog posts on user experience design can be found at http://blog.learningtree.com/tag/ui/.

comments powered by Disqus

Featured

  • Compare New GitHub Copilot Free Plan for Visual Studio/VS Code to Paid Plans

    The free plan restricts the number of completions, chat requests and access to AI models, being suitable for occasional users and small projects.

  • Diving Deep into .NET MAUI

    Ever since someone figured out that fiddling bits results in source code, developers have sought one codebase for all types of apps on all platforms, with Microsoft's latest attempt to further that effort being .NET MAUI.

  • Copilot AI Boosts Abound in New VS Code v1.96

    Microsoft improved on its new "Copilot Edit" functionality in the latest release of Visual Studio Code, v1.96, its open-source based code editor that has become the most popular in the world according to many surveys.

  • AdaBoost Regression Using C#

    Dr. James McCaffrey from Microsoft Research presents a complete end-to-end demonstration of the AdaBoost.R2 algorithm for regression problems (where the goal is to predict a single numeric value). The implementation follows the original source research paper closely, so you can use it as a guide for customization for specific scenarios.

  • Versioning and Documenting ASP.NET Core Services

    Building an API with ASP.NET Core is only half the job. If your API is going to live more than one release cycle, you're going to need to version it. If you have other people building clients for it, you're going to need to document it.

Subscribe on YouTube