2
\$\begingroup\$

I have a button btnSearch and the event handler btnSearch_Click inside my asp.net web application, using web forms.

(certain variables/controls have been renamed to generic variables)

protected void btnSearch_Click(object sender, EventArgs e)
{
    string n1, n2, n3;
    n1 = txtNum1.Text;
    n2 = txtNum2.Text;
    n3 = txtNum3.Text;

    string base_url = @"~/Details.aspx";
    string query_string = "/?";

    if (!String.IsNullOrWhiteSpace(n1))
        query_string += "&n1=" + n1;

    if (!String.IsNullOrWhiteSpace(n2))
        query_string += "&n2=" + n2;

    if (!String.IsNullOrWhiteSpace(n3))
        query_string += "&n3=" + n3;

    Response.Redirect(base_url + query_string);
}

I have a couple questions on this handler. For one, I know business logic should be handled in a separate method, but would what it is doing considered business logic? It is simply logic to correctly handle a redirect, so I am unsure if that should be separated into a new method or not.

I am also wondering if there is a better way to handle the query string building. I need it to be able to contain up to all 3, but not require all 3 query string be provided, but a bunch of if statements doesn't sit right with me for some reason. I've thought about creating another method to handle those, and returning the appended string, something like:

query_string += Validate_Param(n1);

But I'm not sure if that would make the code less readable or not, forcing the reader to need to investigate another method simply for appending a string.

\$\endgroup\$
3
  • \$\begingroup\$ Which technology is this? Web forms? Please be specific. \$\endgroup\$
    – BCdotWEB
    Sep 13, 2021 at 15:51
  • \$\begingroup\$ Don't forget to url-encode your text values. \$\endgroup\$
    – Zairja
    Sep 13, 2021 at 17:43
  • \$\begingroup\$ Business logic is the one that runs the same way in any type of application: console, web, desktop. \$\endgroup\$ Sep 14, 2021 at 14:53

2 Answers 2

3
\$\begingroup\$

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 }
    });
}
\$\endgroup\$
1
  • \$\begingroup\$ @Austin The extension would add the method into HttpResponse which would gives you the ability to reuse it across the pages. It would also be clear enough to other developers that extension is related only to the web pages and it would always be shown by the intellisense which would add an easy access to the extension. \$\endgroup\$
    – iSR5
    Sep 13, 2021 at 19:37
2
\$\begingroup\$

I am not a web guy, so I will not answer the architecture part here.

You could create a helper method to create urls with query strings:

public static string CreateUrl(
    string url, params (string name, string value)[] queryParams)
{
    var builder = new UriBuilder(url);
    var query = HttpUtility.ParseQueryString(builder.Query);
    foreach (var (name, value) in queryParams) {
        if (!String.IsNullOrEmpty(value)) {
            query[name] = value;
        }
    }
    builder.Query = query.ToString();
    return builder.ToString();
}

I am not using string concatenation to create the url. There are several pitfalls when doing so. e.g., you only need the initial "/?" when at least one parameter has a value. The first one is written as ?name=value whereas the following ones as &name=value. Then values must be escaped if they contain problematic characters. This is all handled automatically when using the library functions.

Use as

string url = Helper.CreateUrl("~/Details.aspx",
    ("n1", txtNum1.Text),
    ("n2", txtNum2.Text),
    ("n3", txtNum3.Text));

Note that by using the new ValueTuple feature of C# 7.0, it is easy to specify a list of name/value pairs as params parameter.

This works also if the base url has predefines parameters.

\$\endgroup\$
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.