How To: Create a Read-Only Dynamic Data Web Site

ASP.NET Dynamic Data enables you to quickly create a Web site that exposes a database. By default, a Dynamic Data Web site supports editing, deleting, and inserting data. However, you can make a site read-only by changing page templates so that the page supports no edit, delete, or insert operations.

By default, a Dynamic Data Web site performs routing to send requests to individual List, Details, Edit, and Insert pages. The model of using these pages for separate operations is known as separate-page mode.

Alternatively, Dynamic Data supports combined-page mode. In this mode, all operations are performed by the ListDetails page. The Global.asax file contains commented-out lines that you can uncomment in order to support combined-page mode.

The first procedure in this topic shows how to make a site read-only when the site uses separate-page mode. The second procedure shows how to make a site read-only when the site uses combined-page mode.

Creating a Read-Only Page for Separate-Page Mode

To make a site read-only in separate-page mode

  1. Open the Global.asax file.

  2. Modify the statement that creates the Dynamic Data routing table to add the List and Details pages, but to exclude the Edit and Insert pages

    The following example shows the updated statement. This statement adds a new route to the System.Web.Routing.RouteCollection object (the routing table), which is represented by the routes variable.

    routes.Add(new DynamicDataRoute("{table}/{action}.aspx") {
            Constraints = new RouteValueDictionary(new { action = "List|Details" }),
            Model = model
        }); 
    
    routes.Add(New DynamicDataRoute("{table}/{action}.aspx") With { _
                .Constraints = New RouteValueDictionary(New With {.Action = "List|Details"}), _
                .Model = model})
    
  3. In the DynamicData\PageTemplates folder, open the Details.aspx page template.

  4. In the markup for the DetailsView control, remove the OnItemDeleted attribute and its value.

  5. Inside the DetailsView control, remove the markup for the HyperLink control and for the LinkButton control from the ItemTemplate element.

    In a read-write Dynamic Data Web site, the HyperLink control links to the Edit page template, and the LinkButton button control creates the Delete button. For a read-only Web site, these controls are not required.

    The following example shows the completed DetailsView control.

    <asp:DetailsView ID="DetailsView1" runat="server" 
        DataSourceID="DetailsDataSource"
        CssClass="detailstable" 
        FieldHeaderStyle-CssClass="bold">
      <Fields>
        <asp:TemplateField>
          <ItemTemplate>
            <%-- HyperLink and LinkButton removed. --%>
          </ItemTemplate>
        </asp:TemplateField>
      </Fields>
    </asp:DetailsView>
    
  6. Open the code-behind file for the Details.aspx page.

  7. Remove the DetailsView1_ItemDeleted method.

  8. Open the List.aspx page template.

  9. Remove the following controls from the GridView control:

    • The HyperLink control whose ID is "EditHyperLink".

    • The LinkButton control whose ID is "DeleteLinkButton".

  10. Save and close all files.

Creating a Read-Only Page for Combined-Page Mode

Making a combined-page mode site read-only is simpler than making a separate-page mode site read-only because you have to remove only some controls from one page. You do not have to modify the Global.asax file.

To make a site read-only in combined-page mode

  1. In the DynamicData\PageTemplates folder, open the ListDetails.aspx page template.

  2. In the markup for the GridView control, remove the attributes and values for the following:

    The following example shows the markup for the completed GridView control.

    <asp:GridView ID="GridView1" runat="server" 
        DataSourceID="GridDataSource" 
        AutoGenerateSelectButton="True"
        AllowPaging="True" AllowSorting="True" 
        OnDataBound="OnGridViewDataBound" 
        OnSelectedIndexChanging="OnGridViewSelectedIndexChanging"
        CssClass="gridview">
      <PagerStyle CssClass="footer" />
      <SelectedRowStyle CssClass="selected" />
      <PagerTemplate>
         <asp:GridViewPager runat="server" />
      </PagerTemplate>
      <EmptyDataTemplate>
          There are currently no items in this table.
      </EmptyDataTemplate>
    </asp:GridView>
    
  3. In the markup for the DetailsView control, remove the attributes and values for the following:

    The following example shows the markup for the completed DetailsView control.

    <asp:DetailsView 
       ID="DetailsView1" 
       runat="server" 
       DataSourceID="DetailsDataSource"
       OnModeChanging="OnDetailsViewModeChanging" 
       OnPreRender="OnDetailsViewPreRender"
       >
    </asp:DetailsView> 
    
  4. Open the code-behind file for the ListDetails.aspx page.

  5. Delete the following methods from the ListDetails.aspx code-behind file:

    The following example shows the completed code-behind file.

    using System;
    using System.Data;
    using System.Configuration;
    using System.Collections;
    using System.Linq;
    using System.Web;
    using System.Web.Security;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Web.UI.WebControls.WebParts;
    using System.Web.UI.HtmlControls;
    using System.Xml.Linq;
    using System.Web.DynamicData;
    
    public partial class ListDetails : System.Web.UI.Page {
        protected void Page_Init(object sender, EventArgs e) {
            DynamicDataManager1.RegisterControl(GridView1, true /*setSelectionFromUrl*/);
            DynamicDataManager1.RegisterControl(DetailsView1);
        }
    
        protected void Page_Load(object sender, EventArgs e) {
            MetaTable table = GridDataSource.GetTable();
            Title = table.DisplayName;
    
            // Disable various options if the table is read-only.
            if (table.IsReadOnly) {
                DetailsPanel.Visible = false;
                GridView1.AutoGenerateSelectButton = false;
                GridView1.AutoGenerateEditButton = false;
                GridView1.AutoGenerateDeleteButton = false;
            }
        }
        protected void OnGridViewDataBound(object sender, EventArgs e) {
            if (GridView1.Rows.Count == 0) {
                DetailsView1.ChangeMode(DetailsViewMode.Insert);
            }
        }
        protected void OnFilterSelectedIndexChanged(object sender, 
                EventArgs e) {
            GridView1.EditIndex = -1;
            GridView1.PageIndex = 0;
            DetailsView1.ChangeMode(DetailsViewMode.ReadOnly);
        }
            protected void OnGridViewSelectedIndexChanging(object sender, 
                EventArgs e) {
            GridView1.EditIndex = -1;
            DetailsView1.ChangeMode(DetailsViewMode.ReadOnly);
        }
    
        protected void OnDetailsViewModeChanging(object sender, 
                DetailsViewModeEventArgs e) {
            if (e.NewMode != DetailsViewMode.ReadOnly) {
                GridView1.EditIndex = -1;
            }
        }
    
        protected void OnDetailsViewPreRender(object sender, 
                EventArgs e) {
            int rowCount = DetailsView1.Rows.Count;
            if (rowCount > 0) {
                SetDeleteConfirmation(DetailsView1.Rows[rowCount - 1]);
            }
        }
    
        private void SetDeleteConfirmation(TableRow row) {
            foreach (Control c in row.Cells[0].Controls) {
                if (c is LinkButton) {
                    LinkButton btn = (LinkButton)c;
                    if (btn.CommandName == 
                           DataControlCommands.DeleteCommandName) {
                        btn.OnClientClick = "return confirm('Are you 
                           sure you want to delete this item?');";
                    }
                }
            }
        }
    }
    
    Imports System.Web.DynamicData
    
    Partial Class ListDetails
        Inherits System.Web.UI.Page
    
    
        Protected Sub Page_Init(ByVal sender As Object, _
                ByVal e As EventArgs)
            DynamicDataManager1.RegisterControl(GridView1, true)
            DynamicDataManager1.RegisterControl(DetailsView1)
        End Sub
    
        Protected Sub Page_Load(ByVal sender As Object, _
                ByVal e As EventArgs)
            Dim table As MetaTable = GridDataSource.GetTable
            Title = table.DisplayName
            GridDataSource.IncludePaths = table.ForeignKeyColumnsNames
            DetailsDataSource.IncludePaths = _
                table.ForeignKeyColumnsNames
            ' Disable various options if the table is read-only.
            If table.IsReadOnly Then
                DetailsPanel.Visible = false
                GridView1.AutoGenerateSelectButton = false
                GridView1.AutoGenerateEditButton = false
                GridView1.AutoGenerateDeleteButton = false
            End If
        End Sub
    
        Protected Sub OnGridViewDataBound(ByVal sender As Object, _
                ByVal e As EventArgs)
            If (GridView1.Rows.Count = 0) Then
                DetailsView1.ChangeMode(DetailsViewMode.Insert)
            End If
        End Sub
    
        Protected Sub OnFilterSelectedIndexChanged(ByVal sender As _
                Object, ByVal e As EventArgs)
            GridView1.EditIndex = -1
            GridView1.PageIndex = 0
            DetailsView1.ChangeMode(DetailsViewMode.ReadOnly)
        End Sub
    
        Protected Sub OnGridViewSelectedIndexChanging(ByVal sender As _
                Object, ByVal e As EventArgs)
            GridView1.EditIndex = -1
            DetailsView1.ChangeMode(DetailsViewMode.ReadOnly)
        End Sub
    
        Protected Sub OnGridViewRowDeleted(ByVal sender As Object, _
                ByVal e As GridViewDeletedEventArgs)
            DetailsView1.DataBind
        End Sub
    
        Protected Sub OnGridViewRowUpdated(ByVal sender As Object, _
                ByVal e As GridViewUpdatedEventArgs)
            DetailsView1.DataBind
        End Sub
    
        Protected Sub OnDetailsViewItemDeleted(ByVal sender As Object, _
                ByVal e As DetailsViewDeletedEventArgs)
            GridView1.DataBind
        End Sub
    
        Protected Sub OnDetailsViewItemUpdated(ByVal sender As Object, _
                ByVal e As DetailsViewUpdatedEventArgs)
            GridView1.DataBind
        End Sub
    
        Protected Sub OnDetailsViewItemInserted(ByVal sender As Object, _
                ByVal e As DetailsViewInsertedEventArgs)
            GridView1.DataBind
        End Sub
    
        Protected Sub OnDetailsViewModeChanging(ByVal sender As Object, _
                ByVal e As DetailsViewModeEventArgs)
            If (e.NewMode <> DetailsViewMode.ReadOnly) Then
                GridView1.EditIndex = -1
            End If
        End Sub
    
        Protected Sub OnDetailsViewPreRender(ByVal sender As Object, _
                ByVal e As EventArgs)
            Dim rowCount As Integer = DetailsView1.Rows.Count
            If (rowCount > 0) Then
                SetDeleteConfirmation(DetailsView1.Rows((rowCount - 1)))
            End If
        End Sub
    
        Private Sub SetDeleteConfirmation(ByVal row As TableRow)
            For Each c As Control In row.Cells(0).Controls
                If (TypeOf c Is LinkButton) Then
                    Dim btn As LinkButton = CType(c,LinkButton)
                    If (btn.CommandName = 
                            DataControlCommands.DeleteCommandName) Then
                        btn.OnClientClick = "return confirm( _
                           'Are you sure you want to delete this item?');"
                    End If
                End If
            Next
        End Sub
    End Class
    

See Also

Concepts

ASP.NET Dynamic Data Overview

Change History

Date

History

Reason

July 2008

Added topic.

SP1 feature change.