c# – Best Practice for Button Event Handler

for this button handler, I don’t see a need for a separated method. However, you need an extension method instead, which would be useful in your case.

public static class HttpResponseExtensions
{
    public static void Redirect(this HttpResponse response , string url , Dictionary<string , string> queryString) => Redirect(response , url , queryString , false);

    public static void Redirect(this HttpResponse response , string url , Dictionary<string , string> queryString, bool endResponse)
    {
        if(queryString?.Count == 0)
        {
            response.Redirect(url, endResponse);
        }

        var builder = new StringBuilder(url);

        var query = string.Join("&" , queryString
                                            .Where(x => !string.IsNullOrWhiteSpace(x.Value))
                                            .Select(x => $"{x.Key.Trim()}={x.Value.Trim()}"));
        builder
            .Append("?")
            .Append(HttpUtility.UrlEncode(query));

        response.Redirect(builder.ToString(), endResponse);
    }

}

Then, your btnSearch_Click should be like :

protected void btnSearch_Click(object sender, EventArgs e)
{
    Response.Redirect("~/Details.aspx" , new Dictionary<string , string>
    {
        {"n1", txtNum1.Text },
        {"n2", txtNum2.Text },
        {"n3", txtNum3.Text }
    });
}