title: GridView Row Redirect to Pre-filled DetailsView on Button Click
body: <p><strong>Background</strong>:</p>
  
  <p>I have a GridView which gets populated from an SqlDataSource via DataSourceID. The rows show some summary data from an SQL View. Upon clicking a row, I would like to take my user to another page with a DetailsView control which gets populated with the full set of values from the DB related to the row clicked. My user should be able to edit the data, download files associated with the record, and create a new record of a different type based on said data.</p>
  
  <p><strong>Error</strong>:</p>
  
  <p>All examples that I've found for Clickable GridView rows end up with some variation of the error <code>Invalid postback or callback argument.  Event validation is enabled using &lt;pages enableEventValidation="true"/&gt; in configuration or &lt;%@ Page EnableEventValidation="true" %&gt; in a page.</code></p>
  
  <p>Naturally, I do not want to expose my site to vulnerabilities by disabling event validation. I need to be able to grab the Primary key of the clicked row's associated record and perform operations on that data on a subsequent page, probably via a DetailsView. I suspect my errors are a result of my setup, which is why I included those details.</p>
  
  <p><strong>My Questions Are</strong>:</p>
  
  <ol>
  <li>How do I capture the Primary Key of clicked row?</li>
  <li>How do I, onclick, forward to a "details" page with a pre-filled form containing data from the row record that was clicked?</li>
  </ol>
  
  <h2>HERE'S THE COMPLETE SOLUTION</h2>
  
  <p>**thanks again to Icarus' help</p>
  
  <pre><code>'Fetch the DataKey ("ID"), seems to work
  Protected Sub RowBind(ByVal sender As Object, ByVal e As GridViewRowEventArgs) _
      Handles GridView1.RowDataBound
  
      If e.Row.RowType = DataControlRowType.DataRow Then
          Dim datakey As String = GridView1.DataKeys(e.Row.RowIndex).Value.ToString()
      End If
  End Sub
  'Handle button click
  Protected Sub RowClick(ByVal sender As Object, ByVal e As GridViewCommandEventArgs) _
      Handles GridView1.RowCommand
  
      If e.CommandName = "Select" Then
          'Add to session variable; translate the index of clicked to Primary Key
          Session.Add("DetailsKey", GridView1.DataKeys(e.CommandArgument).Value.ToString)
          Response.Redirect("details.aspx")
      End If
  End Sub
  </code></pre>
  
  <p>And My Markup</p>
  
  <pre><code>&lt;asp:GridView ID="GridView1" runat="server" DataSourceID="GridView1SDS"
      DataKeyNames="ID" AllowPaging="True" AllowSorting="True"&gt;
      '&lt;!-- Styling --&gt;
      &lt;Columns&gt;
          &lt;asp:ButtonField ButtonType="Button" Text="Details" CommandName="Select" /&gt;
      &lt;/Columns&gt;
  &lt;/asp:GridView&gt;
  &lt;asp:SqlDataSource ID="GridView1SDS" runat="server"
      ConnectionString="&lt;%$ ConnectionStrings:dbConnectionString %&gt;"
      SelectCommand="select * from viewRequestQueue"&gt;'&lt;!-- An SQL View --&gt;
  &lt;/asp:SqlDataSource&gt;
  </code></pre>
  
  <p>Forwarded Page VB &amp; Markup</p>
  
  <pre><code>Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
      If Not IsPostBack Then
          GridView2SDS.SelectCommand = "select * from viewRequestQueue where ID = " _
              + Session.Item("DetailsKey").ToString
      End If
  End Sub
  
  &lt;asp:DetailsView ID="GridView2" runat="server" DataSourceID="GridView2SDS"&gt;
      '&lt;!-- Styling --&gt;
  &lt;/asp:DetailsView&gt;
  &lt;asp:SqlDataSource ID="GridView2SDS" runat="server"
      ConnectionString="&lt;%$ ConnectionStrings:dbConnectionString %&gt;"&gt;
  &lt;/asp:SqlDataSource&gt;
  </code></pre>
  
  <p>Also, please note that if the <code>SelectCommand</code> for your DataSource is handled in the codebehind, that means the DataBind will overwrite your <code>&lt;Columns&gt;</code> in the markup. To get around this, you should define the columns in the code behind before the DataBind. So say I wanted to add another ButtonField column to my forwarded page (notice the SelectCommand is not provided in the markup), I added the following before the setting the SelectCommand and doing the DataBind:</p>
  
  <pre><code>Dim id As New ButtonField()
  id.ButtonType = ButtonType.Button
  id.Text = "Load"
  id.CommandName = "Select"
  PubDetails.Columns.Add(id)
  </code></pre>