static void

ASP Detail View

DetailsView is nice but there's a lot of similar code every time. Like this... (In practice, all the BoundFields would be TemplateFields because you need validators)
This uses an identity column. See a Guid version.

Markup

<%--    SqlDataSource    --%>

<asp:SqlDataSource ID="SqlDataSourceDetail" runat="server" ConnectionString="<%$ ConnectionStrings:ConnectionString %>"

    InsertCommand="INSERT INTO [Product] ([Name], [Price], [AvailableFrom], [Category_Id]) VALUES (@Name, @Price, @AvailableFrom, @Category_Id);SET @Id = SCOPE_IDENTITY()"

    SelectCommand="SELECT [Id], [Name], [Price], [AvailableFrom], [Category_Id] FROM [Product] WHERE ([Id] = @Id)"

    UpdateCommand="UPDATE [Product] SET [Name] = @Name, [Price] = @Price, [AvailableFrom] = @AvailableFrom, [Category_Id] = @Category_Id WHERE [Id] = @Id"

    OnInserted="SqlDataSourceDetail_Inserted">

    <SelectParameters>

        <asp:QueryStringParameter DefaultValue="0" Name="Id" QueryStringField="Id" Type="Int32" />

    </SelectParameters>

    <UpdateParameters>

        <asp:Parameter Name="Name" Type="String" />

        <asp:Parameter Name="Price" Type="Decimal" />

        <asp:Parameter Name="AvailableFrom" Type="DateTime" />

        <asp:Parameter Name="Category_Id" Type="Int32" />

        <asp:Parameter Name="Id" Type="Int32" />

    </UpdateParameters>

    <InsertParameters>

        <asp:Parameter Name="Name" Type="String" />

        <asp:Parameter Name="Price" Type="Decimal" />

        <asp:Parameter Name="AvailableFrom" Type="DateTime" />

        <asp:Parameter Name="Category_Id" Type="Int32" />

        <asp:Parameter Name="Id" Type="Int32" Direction="Output" />

    </InsertParameters>

</asp:SqlDataSource>

<%--    Foreign key datasource    --%>

<asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:ConnectionString %>"

    SelectCommand="SELECT [Id], [Name] FROM [Category]"></asp:SqlDataSource>

<%--    UI- DetailsView    --%>

<asp:DetailsView runat="server" ID="DetailsView1" DataSourceID="SqlDataSourceDetail"

    DataKeyNames="Id" AutoGenerateEditButton="True" AutoGenerateInsertButton="True"

    AutoGenerateRows="False" OnItemInserted="DetailsView1_ItemInserted" OnItemUpdated="DetailsView1_ItemUpdated"

    OnModeChanging="DetailsView1_ModeChanging">

    <Fields>

        <asp:BoundField DataField="Id" HeaderText="Id" InsertVisible="False" ReadOnly="True"

            SortExpression="Id" />

        <asp:BoundField DataField="Name" HeaderText="Name" SortExpression="Name" />

        <asp:BoundField DataField="Price" DataFormatString="{0:c}" HeaderText="Price" SortExpression="Price" />

        <asp:BoundField ApplyFormatInEditMode="True" DataField="AvailableFrom" DataFormatString="{0:d}"

            HeaderText="AvailableFrom" SortExpression="AvailableFrom" />

        <asp:TemplateField HeaderText="Category">

            <EditItemTemplate>

                <asp:DropDownList runat="server" ID="ddlCategory" DataSourceID="SqlDataSource1" DataValueField="Id"

                    DataTextField="Name" SelectedValue='<%# Bind("Category_Id") %>' />

            </EditItemTemplate>

        </asp:TemplateField>

    </Fields>

</asp:DetailsView>

Code Behind

#region Standard DetailsView Events

 

/// <summary>

/// Initializes the DetailsView (called from Page_Load)

/// Checks querystring id to swap the detailsView mode between insert and update

/// </summary>

/// <returns></returns>

private bool DetailsViewInit()

{

    if (string.IsNullOrEmpty(Request.QueryString["Id"]))

        DetailsView1.ChangeMode(DetailsViewMode.Insert);

    else

    {

        int result;

        if (!Int32.TryParse(Request.QueryString["Id"], out result))

        {

            Page.Validators.Add(new BusinessValidationError("The ID is not in correct format."));

            DetailsView1.Visible = false;

            return false;

        }

        DetailsView1.ChangeMode(DetailsViewMode.Edit);

    }

    return true;

}

 

/// <summary>

/// After you've updated or inserted or cancelled, this is what happens next...

/// </summary>

protected void PostUpdateAction()

{

    Response.Redirect("TestGridView.aspx");

    //or hide/show panels

}

 

//if you're editing and Select returns no data, handle it

protected static void DetailsView1_ItemCreated(object sender, EventArgs e)

{

    var dv = (DetailsView)sender;

 

    if ((dv.CurrentMode == DetailsViewMode.Edit) &&

        (dv.DataItemCount == 0))

    {

        dv.Page.Validators.Add(new BusinessValidationError("ID doesn't exist"));

        return;

    }

}

 

protected void DetailsView1_ModeChanging(object sender, DetailsViewModeEventArgs e)

{

    if (e.CancelingEdit) PostUpdateAction();

}

 

protected void DetailsView1_ItemUpdated(object sender, DetailsViewUpdatedEventArgs e)

{

    if (HasSqlError(e)) return;

    PostUpdateAction();

}

 

protected void DetailsView1_ItemInserted(object sender, DetailsViewInsertedEventArgs e)

{

    if (HasSqlError(e)) return;

    PostUpdateAction();

}

 

#endregion

 

/// <summary>

/// Handles the Inserted event of the SqlDataSourceDetail control.

/// Shows the identity that has been created

/// (because we added SET @Id = SCOPE_IDENTITY() tp the commandText)

/// </summary>

protected void SqlDataSourceDetail_Inserted(object sender, SqlDataSourceStatusEventArgs e)

{

    if (e.Exception == null)

    {

        DbCommand command = e.Command;

        int id = (int)command.Parameters["@Id"].Value;

        Page.Validators.Add(new BusinessValidationError(id + " added"));

    }

}

 

#region HasSqlError overloads

/// <summary>

/// Determines whether has SQL error. Called from DetailsView1_ItemUpdated

/// </summary>

protected bool HasSqlError(DetailsViewUpdatedEventArgs e)

{

    if (!HasSqlError(e.Exception)) return false;

    e.ExceptionHandled = true;

    return true;

}

 

/// <summary>

/// Determines whether has SQL error. Called from DetailsView1_ItemInserted

/// </summary>

protected bool HasSqlError(DetailsViewInsertedEventArgs e)

{

    if (!HasSqlError(e.Exception)) return false;

    e.ExceptionHandled = true;

    return true;

}

 

/// <summary>

/// Determines whether has SQL error, the foundation.

/// You probably should use template fields with validators, but you probably won't check uniqueness constraints.

/// </summary>

protected bool HasSqlError(Exception ex)

{

    if (ex != null)

    {

        string msg = ex.Message;

        if (ex is FormatException) msg = "Invalid data- check numbers and dates";

        SqlException exSql = ex as SqlException;

        if (exSql != null)

        {

            switch (exSql.Number) //check for others if rqd

            {

                case 2627:

                    msg = "Data is not unique";

                    break;

                case 515:

                    msg = "Mandatory fields must be entered";

                    break;

            }

        }

        Page.Validators.Add(new BusinessValidationError(msg));

        return true;

    }

    return false;

}

#endregion