Monday, June 02, 2008

Eliminate Ambiguous Object References when Customizing ADO.NET Dynamic Data Pages in Web Apps

Most, if not all, Microsoft examples and screencasts for scaffolding and then customizing individual ADO.NET Dynamic Data pages use file-system Web Sites.

You can apply the metadata attributes that Maíra Wenzel describes in her Dynamic Data Attributes post of April 24, 2008 by creating a partial class and EntityNameMetaData class for the table as shown here for Northwind's Order_Details:

public partial class Order_Detail { }

public class Order_DetailMetaData
    [Required(ErrorMessage = "The Quantity field is required")]
    public object Quantity { get; set; }

    [DisplayFormat(DataFormatString = "{0:c}")]
    [Required(ErrorMessage = "The UnitPrice field is required")]
    public object UnitPrice { get; set; }

    [Range(0.0, 0.25, ErrorMessage="Discount must range from 0% to 25%")]
    [DisplayFormat(DataFormatString = "{0:p1}")]
    public object Discount { get; set; }

Note: The runtime detects if Quantity is the wrong data type (string or having a decimal fraction.)

If you want to change the field sequence or make other modifications beyond the capabilities of metadata attributes, you must create a custom page with the appropriate databound control(s) and specify the DynamicFields in sequence.

Customizing a Web Site Page

The standard process (without using the Dynamic Data Website Wizard) to customize a scaffolded page is:

  1. Create the file-system site by opening a new Dynamic Data Web Site (for a LINQ to SQL back end) or Dynamic Data Entities Web Site.
  2. Add new LINQ to SQL Classes or ADO.NET Entity Data Model designer and class files for your database to the project.
  3. Add to the CustomPages folder a subfolder named for the source EntitySet/Table, such as Order_Details for a Northwind example. A subfolder of CustomPages named for the EntitySet intercepts the routed request, such as http://localhost:52080/Order_Details/List.aspx, and redirects the request from the dynamic PageTemplate to the static version.
  4. Copy the appropriate template (such as List.aspx) and its code-behind file (List.aspx.cs) from the PageTemplates folder to the Custom Pages subfolder.
  5. Open the copied template, add an AutogenerateColumns="false" directive and delete the code between the <Columns> and </Columns> tags.
  6. Add DynamicField elements in the sequence you want them to appear in your list or form, as shown here:
<asp:GridView ID="GridView1" runat="server" DataSourceID="GridDataSource"
    AllowPaging="True" AllowSorting="True" CssClass="gridview"
        <asp:DynamicField DataField="Order" />
        <asp:DynamicField DataField="Product" />
        <asp:DynamicField DataField="Quantity" />
        <asp:DynamicField DataField="UnitPrice" />
        <asp:DynamicField DataField="Discount" />        

Note: When customizing DetailsViews (Insert.aspx, Edit.aspx and Details.aspx), replace AutogenerateColumns with AutogenerateRows and <Columns> with <Rows>.

The preceding steps in a Web Site project behave as expected in a Web Site project and deliver a list that appears as shown here:

Customizing a Web Application Page and Clearing Name Collision Errors

If you use the preceding process with a Web Application and run the project, you receive a sequence of errors, such as the following:

The problem is name collisions within a common namespace, ASPNetDynamicDataWebApp for this example. These conflicts don't occur with Web Sites because their files don't define namespaces.

Note: When copying *.aspx files to Custom Pages subfolders in Web Apps, include the designer page *.aspx.designer.cs or .vb.

To clear the errors, just change the namespace in the *.aspx file's <page ... Inherits="Namespace.Page"> directive and the *.aspx.cs or *.aspx.vb file's namespace to something else, such as ASPNetDynamicDataCustom, then run the project.

The ASP.NET forum post on this topic is Unable to Create Custom Pages with Web Application Projects; Web Site Projects Work OK (5/23 Drop) of 6/1/2008.

Stay tuned for more about ASP.NET Dynamic Data projects in Visual Studio Magazine's September 2008 issue.